diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4a9cccfe76..56d74fc148 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,40 @@ +2011-05-12 Kwok Cheung Yeung + + * breakpoint.c (disable_breakpoint): Disable all locations + associated with a tracepoint on target if a trace experiment is + running. + (disable_command): Disable a specific tracepoint location on target if + a trace experiment is running. + (do_enable_breakpoint): Enable all locations associated with a + tracepoint on target if a trace experiment is running. + (enable_command) Enable a specific tracepoint location on target if a + trace experiment is running. + * target.c (update_current_target): Add INHERIT and de_fault clauses for + to_supports_enable_disable_tracepoint, to_enable_tracepoint and + to_disable_tracepoint. + * target.h: Add declaration of struct bp_location. + (struct target_ops): Add new functions + to_supports_enable_disable_tracepoint, to_enable_tracepoint and + to_disable_tracepoint to target operations. + (target_supports_enable_disable_tracepoint): New macro. + (target_enable_tracepoint): New macro. + (target_disable_tracepoint): New macro. + * remote.c (struct remote_state): Add new field. + (remote_enable_disable_tracepoint_feature): New. + (remote_protocol_features): Add new entry. + (remote_supports_enable_disable_tracepoint): New. + (remote_enable_tracepoint): New. + (remote_disable_tracepoint): New. + (init_remote_ops): Add remote_enable_tracepoint, + remote_disable_tracepoint and remote_supports_enable_disable_tracepoint + to remote operations. + * tracepoint.c (start_tracing): Allow tracing to start without any + tracepoints enabled with just a warning if they can be re-enabled + later. + * NEWS: Add news item for the new behaviour of the enable and disable + GDB commands when applied to tracepoints. + Add news items for the new remote packets QTEnable and QTDisable. + 2011-05-11 Jan Kratochvil * config.in: Regenerate. diff --git a/gdb/NEWS b/gdb/NEWS index e735293289..e749015fda 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -27,6 +27,23 @@ watch EXPRESSION mask MASK_VALUE The watch command now supports the mask argument which allows creation of masked watchpoints, if the current architecture supports this feature. +* Tracepoints can now be enabled and disabled at any time after a trace + experiment has been started using the standard "enable" and "disable" + commands. It is now possible to start a trace experiment with no enabled + tracepoints; GDB will display a warning, but will allow the experiment to + begin, assuming that tracepoints will be enabled as needed while the trace + is running. + +* New remote packets + +QTEnable + + Dynamically enable a tracepoint in a started trace experiment. + +QTDisable + + Dynamically disable a tracepoint in a started trace experiment. + *** Changes in GDB 7.3 * GDB has a new command: "thread find [REGEXP]". diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index e582c36c8a..9ce3806baa 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -11685,6 +11685,15 @@ disable_breakpoint (struct breakpoint *bpt) bpt->enable_state = bp_disabled; + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && is_tracepoint (bpt)) + { + struct bp_location *location; + + for (location = bpt->loc; location; location = location->next) + target_disable_tracepoint (location); + } + update_global_location_list (0); observer_notify_breakpoint_modified (bpt); @@ -11714,7 +11723,13 @@ disable_command (char *args, int from_tty) { struct bp_location *loc = find_location_by_number (args); if (loc) - loc->enabled = 0; + { + loc->enabled = 0; + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && loc->owner + && is_tracepoint (loc->owner)) + target_disable_tracepoint (loc); + } update_global_location_list (0); } else @@ -11762,6 +11777,16 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition) if (bpt->enable_state != bp_permanent) bpt->enable_state = bp_enabled; + + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && is_tracepoint (bpt)) + { + struct bp_location *location; + + for (location = bpt->loc; location; location = location->next) + target_enable_tracepoint (location); + } + bpt->disposition = disposition; update_global_location_list (1); breakpoints_changed (); @@ -11804,7 +11829,13 @@ enable_command (char *args, int from_tty) { struct bp_location *loc = find_location_by_number (args); if (loc) - loc->enabled = 1; + { + loc->enabled = 1; + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && loc->owner + && is_tracepoint (loc->owner)) + target_enable_tracepoint (loc); + } update_global_location_list (1); } else diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 1a987ef7df..40f93eef09 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,10 @@ +2011-05-12 Kwok Cheung Yeung + + * gdb.texinfo: Document change in the behaviour of the enable and + disable GDB commands when applied to tracepoints. + Document the EnableDisableTracepoints remote stub feature. + Document QTEnable and QTDisable in the list of tracepoint packets. + 2011-05-11 Jan Kratochvil * Makefile.in (GDB_DOC_SOURCE_INCLUDES): Rename inc-hist.texinfo to diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index da2c784c70..67436dd56f 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -10026,14 +10026,20 @@ These commands are deprecated; they are equivalent to plain @code{disable} and @ @item disable tracepoint @r{[}@var{num}@r{]} Disable tracepoint @var{num}, or all tracepoints if no argument @var{num} is given. A disabled tracepoint will have no effect during -the next trace experiment, but it is not forgotten. You can re-enable +a trace experiment, but it is not forgotten. You can re-enable a disabled tracepoint using the @code{enable tracepoint} command. +If the command is issued during a trace experiment and the debug target +has support for disabling tracepoints during a trace experiment, then the +change will be effective immediately. Otherwise, it will be applied to the +next trace experiment. @kindex enable tracepoint @item enable tracepoint @r{[}@var{num}@r{]} -Enable tracepoint @var{num}, or all tracepoints. The enabled -tracepoints will become effective the next time a trace experiment is -run. +Enable tracepoint @var{num}, or all tracepoints. If this command is +issued during a trace experiment and the debug target supports enabling +tracepoints during a trace experiment, then the enabled tracepoints will +become effective immediately. Otherwise, they will become effective the +next time a trace experiment is run. @end table @node Tracepoint Passcounts @@ -33627,6 +33633,11 @@ These are the currently defined stub features and their properties: @tab @samp{-} @tab No +@item @samp{EnableDisableTracepoints} +@tab No +@tab @samp{-} +@tab No + @end multitable These are the currently defined stub features, in more detail: @@ -33739,6 +33750,11 @@ The remote stub understands the @samp{QAllow} packet. @cindex static tracepoints, in remote protocol The remote stub supports static tracepoints. +@item EnableDisableTracepoints +The remote stub supports the @samp{QTEnable} (@pxref{QTEnable}) and +@samp{QTDisable} (@pxref{QTDisable}) packets that allow tracepoints +to be enabled and disabled while a trace experiment is running. + @end table @item qSymbol:: @@ -33819,6 +33835,8 @@ packets.) @item qTsV @itemx QTStart @itemx QTStop +@itemx QTEnable +@itemx QTDisable @itemx QTinit @itemx QTro @itemx qTStatus @@ -34308,6 +34326,18 @@ instruction reply packet}). @item QTStop End the tracepoint experiment. Stop collecting trace frames. +@item QTEnable:@var{n}:@var{addr} +@anchor{QTEnable} +Enable tracepoint @var{n} at address @var{addr} in a started tracepoint +experiment. If the tracepoint was previously disabled, then collection +of data from it will resume. + +@item QTDisable:@var{n}:@var{addr} +@anchor{QTDisable} +Disable tracepoint @var{n} at address @var{addr} in a started tracepoint +experiment. No more data will be collected from the tracepoint unless +@samp{QTEnable:@var{n}:@var{addr}} is subsequently issued. + @item QTinit Clear the table of tracepoints, and empty the trace frame buffer. diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index bea804d9ab..c5ae99fd9c 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,18 @@ +2011-05-12 Kwok Cheung Yeung + + * server.c (handle_query): Add EnableDisableTracepoints to the list + of supported features. + * tracepoint.c (clear_installed_tracepoints): Uninstall disabled + tracepoints. + (cmd_qtenable_disable): New. + (cmd_qtstart): Install tracepoints even if disabled. + (handle_tracepoint_general_set): Add call to cmd_qtenable_disable on + receiving a QTEnable or QTDisable packet. + (gdb_collect): Skip data collection if fast tracepoint is disabled. + (ust_marker_to_static_tracepoint): Do not ignore disabled static + tracepoints. + (gdb_probe): Skip data collection if static tracepoint is disabled. + 2011-05-10 Doug Evans * thread-db.c (thread_db_handle_monitor_command): Handle elided path. diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 6bf6eaac00..fd06c8f9a2 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -1540,6 +1540,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) strcat (own_buf, ";StaticTracepoints+"); strcat (own_buf, ";qXfer:statictrace:read+"); strcat (own_buf, ";qXfer:traceframe-info:read+"); + strcat (own_buf, ";EnableDisableTracepoints+"); } return; diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index 0916835115..dc1050e4c7 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -2214,9 +2214,6 @@ clear_installed_tracepoints (void) /* Restore any bytes overwritten by tracepoints. */ for (tpoint = tracepoints; tpoint; tpoint = tpoint->next) { - if (!tpoint->enabled) - continue; - /* Catch the case where we might try to remove a tracepoint that was never actually installed. */ if (tpoint->handle == NULL) @@ -2454,6 +2451,73 @@ cmd_qtdv (char *own_buf) write_ok (own_buf); } +static void +cmd_qtenable_disable (char *own_buf, int enable) +{ + char *packet = own_buf; + ULONGEST num, addr; + struct tracepoint *tp; + + packet += strlen (enable ? "QTEnable:" : "QTDisable:"); + packet = unpack_varlen_hex (packet, &num); + ++packet; /* skip a colon */ + packet = unpack_varlen_hex (packet, &addr); + + tp = find_tracepoint (num, addr); + + if (tp) + { + if ((enable && tp->enabled) || (!enable && !tp->enabled)) + { + trace_debug ("Tracepoint %d at 0x%s is already %s", + (int) num, paddress (addr), + enable ? "enabled" : "disabled"); + write_ok (own_buf); + return; + } + + trace_debug ("%s tracepoint %d at 0x%s", + enable ? "Enabling" : "Disabling", + (int) num, paddress (addr)); + + tp->enabled = enable; + + if (tp->type == fast_tracepoint || tp->type == static_tracepoint) + { + int ret; + int offset = offsetof (struct tracepoint, enabled); + CORE_ADDR obj_addr = tp->obj_addr_on_target + offset; + + ret = prepare_to_access_memory (); + if (ret) + { + trace_debug ("Failed to temporarily stop inferior threads"); + write_enn (own_buf); + return; + } + + ret = write_inferior_integer (obj_addr, enable); + done_accessing_memory (); + + if (ret) + { + trace_debug ("Cannot write enabled flag into " + "inferior process memory"); + write_enn (own_buf); + return; + } + } + + write_ok (own_buf); + } + else + { + trace_debug ("Tracepoint %d at 0x%s not found", + (int) num, paddress (addr)); + write_enn (own_buf); + } +} + static void cmd_qtv (char *own_buf) { @@ -2719,9 +2783,6 @@ cmd_qtstart (char *packet) /* Ensure all the hit counts start at zero. */ tpoint->hit_count = 0; - if (!tpoint->enabled) - continue; - if (tpoint->type == trap_tracepoint) { ++slow_tracepoint_count; @@ -3461,6 +3522,16 @@ handle_tracepoint_general_set (char *packet) cmd_qtdpsrc (packet); return 1; } + else if (strncmp ("QTEnable:", packet, strlen ("QTEnable:")) == 0) + { + cmd_qtenable_disable (packet, 1); + return 1; + } + else if (strncmp ("QTDisable:", packet, strlen ("QTDisable:")) == 0) + { + cmd_qtenable_disable (packet, 0); + return 1; + } else if (strncmp ("QTDV:", packet, strlen ("QTDV:")) == 0) { cmd_qtdv (packet); @@ -5340,6 +5411,9 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs) if (!tracing) return; + if (!tpoint->enabled) + return; + ctx.base.type = fast_tracepoint; ctx.regs = regs; ctx.regcache_initted = 0; @@ -6598,7 +6672,7 @@ ust_marker_to_static_tracepoint (const struct marker *mdata) for (tpoint = tracepoints; tpoint; tpoint = tpoint->next) { - if (!tpoint->enabled || tpoint->type != static_tracepoint) + if (tpoint->type != static_tracepoint) continue; if (tpoint->address == (uintptr_t) mdata->location) @@ -6653,6 +6727,12 @@ gdb_probe (const struct marker *mdata, void *probe_private, return; } + if (!tpoint->enabled) + { + trace_debug ("gdb_probe: tracepoint disabled"); + return; + } + ctx.tpoint = tpoint; trace_debug ("gdb_probe: collecting marker: " diff --git a/gdb/remote.c b/gdb/remote.c index 76c137a2d1..ff64b04224 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -329,6 +329,10 @@ struct remote_state disconnected. */ int disconnected_tracing; + /* True if the stub reports support for enabling and disabling + tracepoints while a trace experiment is running. */ + int enable_disable_tracepoints; + /* Nonzero if the user has pressed Ctrl-C, but the target hasn't responded to that. */ int ctrlc_pending_p; @@ -3689,6 +3693,16 @@ remote_disconnected_tracing_feature (const struct protocol_feature *feature, rs->disconnected_tracing = (support == PACKET_ENABLE); } +static void +remote_enable_disable_tracepoint_feature (const struct protocol_feature *feature, + enum packet_support support, + const char *value) +{ + struct remote_state *rs = get_remote_state (); + + rs->enable_disable_tracepoints = (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, @@ -3735,6 +3749,8 @@ static struct protocol_feature remote_protocol_features[] = { PACKET_TracepointSource }, { "QAllow", PACKET_DISABLE, remote_supported_packet, PACKET_QAllow }, + { "EnableDisableTracepoints", PACKET_DISABLE, + remote_enable_disable_tracepoint_feature, -1 }, }; static char *remote_support_xml; @@ -9648,6 +9664,14 @@ remote_supports_static_tracepoints (void) return rs->static_tracepoints; } +static int +remote_supports_enable_disable_tracepoint (void) +{ + struct remote_state *rs = get_remote_state (); + + return rs->enable_disable_tracepoints; +} + static void remote_trace_init (void) { @@ -9918,6 +9942,38 @@ remote_download_trace_state_variable (struct trace_state_variable *tsv) error (_("Error on target while downloading trace state variable.")); } +static void +remote_enable_tracepoint (struct bp_location *location) +{ + struct remote_state *rs = get_remote_state (); + char addr_buf[40]; + + sprintf_vma (addr_buf, location->address); + sprintf (rs->buf, "QTEnable:%x:%s", location->owner->number, addr_buf); + putpkt (rs->buf); + remote_get_noisy_reply (&rs->buf, &rs->buf_size); + if (*rs->buf == '\0') + error (_("Target does not support enabling tracepoints while a trace run is ongoing.")); + if (strcmp (rs->buf, "OK") != 0) + error (_("Error on target while enabling tracepoint.")); +} + +static void +remote_disable_tracepoint (struct bp_location *location) +{ + struct remote_state *rs = get_remote_state (); + char addr_buf[40]; + + sprintf_vma (addr_buf, location->address); + sprintf (rs->buf, "QTDisable:%x:%s", location->owner->number, addr_buf); + putpkt (rs->buf); + remote_get_noisy_reply (&rs->buf, &rs->buf_size); + if (*rs->buf == '\0') + error (_("Target does not support disabling tracepoints while a trace run is ongoing.")); + if (strcmp (rs->buf, "OK") != 0) + error (_("Error on target while disabling tracepoint.")); +} + static void remote_trace_set_readonly_regions (void) { @@ -10308,10 +10364,13 @@ Specify the serial device it is connected to\n\ remote_ops.to_terminal_ours = remote_terminal_ours; remote_ops.to_supports_non_stop = remote_supports_non_stop; remote_ops.to_supports_multi_process = remote_supports_multi_process; + remote_ops.to_supports_enable_disable_tracepoint = remote_supports_enable_disable_tracepoint; remote_ops.to_trace_init = remote_trace_init; remote_ops.to_download_tracepoint = remote_download_tracepoint; remote_ops.to_download_trace_state_variable = remote_download_trace_state_variable; + remote_ops.to_enable_tracepoint = remote_enable_tracepoint; + remote_ops.to_disable_tracepoint = remote_disable_tracepoint; remote_ops.to_trace_set_readonly_regions = remote_trace_set_readonly_regions; remote_ops.to_trace_start = remote_trace_start; remote_ops.to_get_trace_status = remote_get_trace_status; diff --git a/gdb/target.c b/gdb/target.c index 9c522cb39a..ed2da34744 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -659,9 +659,12 @@ update_current_target (void) INHERIT (to_get_ada_task_ptid, t); /* Do not inherit to_search_memory. */ INHERIT (to_supports_multi_process, t); + INHERIT (to_supports_enable_disable_tracepoint, t); INHERIT (to_trace_init, t); INHERIT (to_download_tracepoint, t); INHERIT (to_download_trace_state_variable, t); + INHERIT (to_enable_tracepoint, t); + INHERIT (to_disable_tracepoint, t); INHERIT (to_trace_set_readonly_regions, t); INHERIT (to_trace_start, t); INHERIT (to_get_trace_status, t); @@ -825,6 +828,9 @@ update_current_target (void) de_fault (to_supports_multi_process, (int (*) (void)) return_zero); + de_fault (to_supports_enable_disable_tracepoint, + (int (*) (void)) + return_zero); de_fault (to_trace_init, (void (*) (void)) tcomplain); @@ -834,6 +840,12 @@ update_current_target (void) de_fault (to_download_trace_state_variable, (void (*) (struct trace_state_variable *)) tcomplain); + de_fault (to_enable_tracepoint, + (void (*) (struct bp_location *)) + tcomplain); + de_fault (to_disable_tracepoint, + (void (*) (struct bp_location *)) + tcomplain); de_fault (to_trace_set_readonly_regions, (void (*) (void)) tcomplain); diff --git a/gdb/target.h b/gdb/target.h index 52e02761a0..fd58bd95c9 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -28,6 +28,7 @@ struct objfile; struct ui_file; struct mem_attrib; struct target_ops; +struct bp_location; struct bp_target_info; struct regcache; struct target_section_table; @@ -644,6 +645,10 @@ struct target_ops simultaneously? */ int (*to_supports_multi_process) (void); + /* Does this target support enabling and disabling tracepoints while a trace + experiment is running? */ + int (*to_supports_enable_disable_tracepoint) (void); + /* Determine current architecture of thread PTID. The target is supposed to determine the architecture of the code where @@ -674,6 +679,12 @@ struct target_ops /* Send full details of a trace state variable to the target. */ void (*to_download_trace_state_variable) (struct trace_state_variable *tsv); + /* Enable a tracepoint on the target. */ + void (*to_enable_tracepoint) (struct bp_location *location); + + /* Disable a tracepoint on the target. */ + void (*to_disable_tracepoint) (struct bp_location *location); + /* Inform the target info of memory regions that are readonly (such as text sections), and so it should return data from those rather than look in the trace buffer. */ @@ -873,6 +884,12 @@ struct address_space *target_thread_address_space (ptid_t); #define target_supports_multi_process() \ (*current_target.to_supports_multi_process) () +/* Returns true if this target can enable and disable tracepoints + while a trace experiment is running. */ + +#define target_supports_enable_disable_tracepoint() \ + (*current_target.to_supports_enable_disable_tracepoint) () + /* Invalidate all target dcaches. */ extern void target_dcache_invalidate (void); @@ -1457,6 +1474,12 @@ extern int target_search_memory (CORE_ADDR start_addr, #define target_download_trace_state_variable(tsv) \ (*current_target.to_download_trace_state_variable) (tsv) +#define target_enable_tracepoint(loc) \ + (*current_target.to_enable_tracepoint) (loc) + +#define target_disable_tracepoint(loc) \ + (*current_target.to_disable_tracepoint) (loc) + #define target_trace_start() \ (*current_target.to_trace_start) () diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 119ab221d5..ab390152e8 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -1583,11 +1583,17 @@ start_tracing (void) (t->type == bp_fast_tracepoint ? "fast " : ""), t->number); } - /* No point in tracing with only disabled tracepoints. */ if (!any_enabled) { - VEC_free (breakpoint_p, tp_vec); - error (_("No tracepoints enabled, not starting trace")); + if (target_supports_enable_disable_tracepoint ()) + warning (_("No tracepoints enabled")); + else + { + /* No point in tracing with only disabled tracepoints that + cannot be re-enabled. */ + VEC_free (breakpoint_p, tp_vec); + error (_("No tracepoints enabled, not starting trace")); + } } if (num_to_download <= 0)