From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15902 invoked by alias); 5 May 2011 17:27:41 -0000 Received: (qmail 15891 invoked by uid 22791); 5 May 2011 17:27:38 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,TW_QT,TW_TD,T_FILL_THIS_FORM_SHORT,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 05 May 2011 17:27:16 +0000 Received: (qmail 22241 invoked from network); 5 May 2011 17:27:15 -0000 Received: from unknown (HELO ?192.168.1.2?) (kcy@127.0.0.2) by mail.codesourcery.com with ESMTPA; 5 May 2011 17:27:15 -0000 Message-ID: <4DC2DDEF.10600@codesourcery.com> Date: Thu, 05 May 2011 17:27:00 -0000 From: Kwok Cheung Yeung User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.17) Gecko/20110414 Thunderbird/3.1.10 MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: [PATCH] Support for enabling/disabling tracepoints while a trace experiment is running Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-05/txt/msg00147.txt.bz2 Tracepoints currently cannot be enabled or disabled while a trace experiment is running (or rather, you can, but it does not take effect until the next tstart command, which would discard all the data collected so far). This ability could be useful, for example, for long running experiments where a tracepoint is discovered to be unneeded after beginning the experiment and can be disabled to avoid wasting trace buffer space. This patch adds support for enabling or disabling tracepoints while an experiment is running, by sending a new remote command to the gdbserver whenever this happens. The gdbserver will then set the enabled flag on the tracepoint accordingly. Kwok Cheung Yeung gdb/ * 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_enable_tracepoint and to_disable_tracepoint. * target.h: Add declaration of struct bp_location. (struct target_ops): Add new function to_enable_tracepoint and to_disable_tracepoint to target operations. (target_enable_tracepoint): New macro. (target_disable_tracepoint): New macro. * remote.c (remote_enable_tracepoint): New. (remote_disable_tracepoint): New. (init_remote_ops): Add remote_enable_tracepoint and remote_disable_tracepoint to remote operations. * tracepoint.c (start_tracing): Allow tracing to start without any tracepoints enabled with just a warning, since they can now be re-enabled. * 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. * gdbserver/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. gdb/doc/ * gdb.texinfo: Document change in the behaviour of the enable and disable GDB commands when applied to tracepoints. Document QTEnable and QTDisable in the list of tracepoint packets. Index: gdb/NEWS =================================================================== RCS file: /cvs/src/src/gdb/NEWS,v retrieving revision 1.436 diff -u -p -r1.436 NEWS --- gdb/NEWS 24 Apr 2011 08:02:18 -0000 1.436 +++ gdb/NEWS 5 May 2011 17:09:54 -0000 @@ -42,6 +42,22 @@ Initial support for the OpenCL C language (http://www.khronos.org/opencl) has been integrated into GDB. +* Tracepoints can now be enabled and disabled at any time after a trace + experiment has been started using the standard "enable" and "disable" + commands. If a trace experiment is started with no enabled + tracepoints, then a warning will be printed but the experiment will + proceed anyway. + +* New remote packets + +QTEnable + + Dynamically enable a tracepoint in a started trace experiment. + +QTDisable + + Dynamically disable a tracepoint in a started trace experiment. + * Python scripting ** The function gdb.Write now accepts an optional keyword 'stream'. Index: gdb/breakpoint.c =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.573 diff -u -p -r1.573 breakpoint.c --- gdb/breakpoint.c 3 May 2011 07:29:17 -0000 1.573 +++ gdb/breakpoint.c 5 May 2011 17:09:57 -0000 @@ -11412,6 +11412,14 @@ disable_breakpoint (struct breakpoint *b bpt->enable_state = bp_disabled; + if (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); @@ -11441,7 +11449,12 @@ disable_command (char *args, int from_tt { struct bp_location *loc = find_location_by_number (args); if (loc) - loc->enabled = 0; + { + loc->enabled = 0; + if (current_trace_status ()->running && loc->owner + && is_tracepoint (loc->owner)) + target_disable_tracepoint (loc); + } update_global_location_list (0); } else @@ -11489,6 +11502,15 @@ do_enable_breakpoint (struct breakpoint if (bpt->enable_state != bp_permanent) bpt->enable_state = bp_enabled; + + if (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 (); @@ -11531,7 +11553,12 @@ 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 (current_trace_status ()->running && loc->owner + && is_tracepoint (loc->owner)) + target_enable_tracepoint (loc); + } update_global_location_list (1); } else Index: gdb/remote.c =================================================================== RCS file: /cvs/src/src/gdb/remote.c,v retrieving revision 1.445 diff -u -p -r1.445 remote.c --- gdb/remote.c 27 Apr 2011 13:29:14 -0000 1.445 +++ gdb/remote.c 5 May 2011 17:10:00 -0000 @@ -9919,6 +9919,38 @@ remote_download_trace_state_variable (st } 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) { asection *s; @@ -10312,6 +10344,8 @@ Specify the serial device it is connecte 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; Index: gdb/target.c =================================================================== RCS file: /cvs/src/src/gdb/target.c,v retrieving revision 1.281 diff -u -p -r1.281 target.c --- gdb/target.c 27 Apr 2011 13:29:15 -0000 1.281 +++ gdb/target.c 5 May 2011 17:10:00 -0000 @@ -659,6 +659,8 @@ update_current_target (void) 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); @@ -831,6 +833,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); Index: gdb/target.h =================================================================== RCS file: /cvs/src/src/gdb/target.h,v retrieving revision 1.204 diff -u -p -r1.204 target.h --- gdb/target.h 27 Apr 2011 13:29:15 -0000 1.204 +++ gdb/target.h 5 May 2011 17:10:01 -0000 @@ -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; @@ -668,6 +669,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. */ @@ -1431,6 +1438,12 @@ extern int target_search_memory (CORE_AD #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) () Index: gdb/tracepoint.c =================================================================== RCS file: /cvs/src/src/gdb/tracepoint.c,v retrieving revision 1.222 diff -u -p -r1.222 tracepoint.c --- gdb/tracepoint.c 19 Apr 2011 18:04:07 -0000 1.222 +++ gdb/tracepoint.c 5 May 2011 17:10:02 -0000 @@ -1583,12 +1583,9 @@ start_tracing (void) (t->type == bp_fast_tracepoint ? "fast " : ""), t->number); } - /* No point in tracing with only disabled tracepoints. */ + /* Warn if tracing with only disabled tracepoints. */ if (!any_enabled) - { - VEC_free (breakpoint_p, tp_vec); - error (_("No tracepoints enabled, not starting trace")); - } + warning (_("No tracepoints enabled")); if (num_to_download <= 0) { Index: gdb/doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.829 diff -u -p -r1.829 gdb.texinfo --- gdb/doc/gdb.texinfo 3 May 2011 15:18:10 -0000 1.829 +++ gdb/doc/gdb.texinfo 5 May 2011 17:10:13 -0000 @@ -10008,15 +10008,14 @@ These commands are deprecated; they are @kindex disable tracepoint @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 disabled tracepoint using the @code{enable tracepoint} command. +@var{num} is given. The change is effective immediately. You +can re-enable a disabled tracepoint using the @code{enable tracepoint} +command. @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. +tracepoints will become effective immediately. @end table @node Tracepoint Passcounts @@ -33794,6 +33793,8 @@ packets.) @item qTsV @itemx QTStart @itemx QTStop +@itemx QTEnable +@itemx QTDisable @itemx QTinit @itemx QTro @itemx qTStatus @@ -34283,6 +34284,16 @@ instruction reply packet}). @item QTStop End the tracepoint experiment. Stop collecting trace frames. +@item QTEnable:@var{n}:@var{addr} +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} +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. Index: gdb/gdbserver/tracepoint.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/tracepoint.c,v retrieving revision 1.24 diff -u -p -r1.24 tracepoint.c --- gdb/gdbserver/tracepoint.c 10 Mar 2011 20:21:14 -0000 1.24 +++ gdb/gdbserver/tracepoint.c 5 May 2011 17:10:14 -0000 @@ -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) @@ -2455,6 +2452,73 @@ cmd_qtdv (char *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) { ULONGEST num; @@ -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 *pac 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, 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 s 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, v return; } + if (!tpoint->enabled) + { + trace_debug ("gdb_probe: tracepoint disabled"); + return; + } + ctx.tpoint = tpoint; trace_debug ("gdb_probe: collecting marker: "