? tmeta-patch-1 Index: breakpoint.c =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.616 diff -p -r1.616 breakpoint.c *** breakpoint.c 12 Oct 2011 15:43:48 -0000 1.616 --- breakpoint.c 17 Oct 2011 15:13:46 -0000 *************** print_one_breakpoint_location (struct br *** 4889,4894 **** --- 4889,4896 ---- /* FIXME should make an annotation for this. */ if (ep_is_catchpoint (b)) ui_out_text (uiout, "\tcatchpoint"); + else if (is_tracepoint (b)) + ui_out_text (uiout, "\ttracepoint"); else ui_out_text (uiout, "\tbreakpoint"); ui_out_text (uiout, " already hit "); *************** print_one_breakpoint_location (struct br *** 4913,4918 **** --- 4915,4932 ---- ui_out_text (uiout, " hits\n"); } + if (!part_of_multiple && is_tracepoint (b)) + { + struct tracepoint *tp = (struct tracepoint *) b; + + if (tp->traceframe_usage) + { + ui_out_text (uiout, "\ttrace buffer usage "); + ui_out_field_int (uiout, "traceframe-usage", tp->traceframe_usage); + ui_out_text (uiout, " bytes\n"); + } + } + l = b->commands ? b->commands->commands : NULL; if (!part_of_multiple && l) { *************** create_tracepoint_from_upload (struct up *** 12848,12853 **** --- 12862,12871 ---- "have no source form, ignoring them"), utp->number); + /* Copy any status information that might be available. */ + tp->base.hit_count = utp->hit_count; + tp->traceframe_usage = utp->traceframe_usage; + return tp; } Index: breakpoint.h =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.h,v retrieving revision 1.161 diff -p -r1.161 breakpoint.h *** breakpoint.h 12 Oct 2011 15:43:49 -0000 1.161 --- breakpoint.h 17 Oct 2011 15:13:46 -0000 *************** struct tracepoint *** 706,711 **** --- 706,715 ---- /* The number of the tracepoint on the target. */ int number_on_target; + /* The total space taken by all the trace frames for this + tracepoint. */ + ULONGEST traceframe_usage; + /* The static tracepoint marker id, if known. */ char *static_trace_marker_id; Index: remote.c =================================================================== RCS file: /cvs/src/src/gdb/remote.c,v retrieving revision 1.465 diff -p -r1.465 remote.c *** remote.c 13 Oct 2011 13:15:16 -0000 1.465 --- remote.c 17 Oct 2011 15:13:46 -0000 *************** remote_get_trace_status (struct trace_st *** 10145,10150 **** --- 10145,10197 ---- return ts->running; } + void + remote_get_tracepoint_status (struct breakpoint *bp, + struct uploaded_tp *utp) + { + struct remote_state *rs = get_remote_state (); + char addrbuf[40]; + char *reply; + struct bp_location *loc; + struct tracepoint *tp = (struct tracepoint *) bp; + + if (tp) + { + tp->base.hit_count = 0; + tp->traceframe_usage = 0; + for (loc = tp->base.loc; loc; loc = loc->next) + { + /* If the tracepoint was never downloaded, don't go asking for + any status. */ + if (tp->number_on_target == 0) + continue; + sprintf_vma (addrbuf, loc->address); + sprintf (rs->buf, "qTP:%x:%s", tp->number_on_target, addrbuf); + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (reply && *reply) + { + if (*reply == 'V') + parse_tracepoint_status (reply + 1, bp, utp); + } + } + } + else if (utp) + { + utp->hit_count = 0; + utp->traceframe_usage = 0; + sprintf_vma (addrbuf, (long unsigned int) utp->addr); + sprintf (rs->buf, "qTP:%x:%s", utp->number, addrbuf); + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (reply && *reply) + { + if (*reply == 'V') + parse_tracepoint_status (reply + 1, bp, utp); + } + } + } + static void remote_trace_stop (void) { *************** remote_traceframe_info (void) *** 10390,10395 **** --- 10437,10485 ---- return NULL; } + static int + remote_set_trace_notes (char *user, char *notes, char *stop_notes) + { + struct remote_state *rs = get_remote_state (); + char *reply; + char *buf = rs->buf; + char *endbuf = rs->buf + get_remote_packet_size (); + int nbytes; + + buf += xsnprintf (buf, endbuf - buf, "QTNotes:"); + if (user) + { + buf += xsnprintf (buf, endbuf - buf, "user:"); + nbytes = bin2hex (user, buf, 0); + buf += 2 * nbytes; + *buf++ = ';'; + } + if (notes) + { + buf += xsnprintf (buf, endbuf - buf, "notes:"); + nbytes = bin2hex (notes, buf, 0); + buf += 2 * nbytes; + *buf++ = ';'; + } + if (stop_notes) + { + buf += xsnprintf (buf, endbuf - buf, "tstop:"); + nbytes = bin2hex (stop_notes, buf, 0); + buf += 2 * nbytes; + *buf++ = ';'; + } + + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (*reply == '\0') + return 0; + + if (strcmp (reply, "OK") != 0) + error (_("Bogus reply from target: %s"), reply); + + return 1; + } + static void init_remote_ops (void) { *************** Specify the serial device it is connecte *** 10468,10473 **** --- 10558,10564 ---- 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; + remote_ops.to_get_tracepoint_status = remote_get_tracepoint_status; remote_ops.to_trace_stop = remote_trace_stop; remote_ops.to_trace_find = remote_trace_find; remote_ops.to_get_trace_state_variable_value *************** Specify the serial device it is connecte *** 10479,10484 **** --- 10570,10576 ---- remote_ops.to_get_raw_trace_data = remote_get_raw_trace_data; remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing; remote_ops.to_set_circular_trace_buffer = remote_set_circular_trace_buffer; + remote_ops.to_set_trace_notes = remote_set_trace_notes; remote_ops.to_core_of_thread = remote_core_of_thread; remote_ops.to_verify_memory = remote_verify_memory; remote_ops.to_get_tib_address = remote_get_tib_address; Index: target.c =================================================================== RCS file: /cvs/src/src/gdb/target.c,v retrieving revision 1.286 diff -p -r1.286 target.c *** target.c 7 Oct 2011 12:06:46 -0000 1.286 --- target.c 17 Oct 2011 15:13:46 -0000 *************** update_current_target (void) *** 680,685 **** --- 680,686 ---- INHERIT (to_trace_set_readonly_regions, t); INHERIT (to_trace_start, t); INHERIT (to_get_trace_status, t); + INHERIT (to_get_tracepoint_status, t); INHERIT (to_trace_stop, t); INHERIT (to_trace_find, t); INHERIT (to_get_trace_state_variable_value, t); *************** update_current_target (void) *** 689,694 **** --- 690,696 ---- INHERIT (to_get_raw_trace_data, t); INHERIT (to_set_disconnected_tracing, t); INHERIT (to_set_circular_trace_buffer, t); + INHERIT (to_set_trace_notes, t); INHERIT (to_get_tib_address, t); INHERIT (to_set_permissions, t); INHERIT (to_static_tracepoint_marker_at, t); *************** update_current_target (void) *** 864,869 **** --- 866,874 ---- de_fault (to_get_trace_status, (int (*) (struct trace_status *)) return_minus_one); + de_fault (to_get_tracepoint_status, + (void (*) (struct breakpoint *, struct uploaded_tp *)) + tcomplain); de_fault (to_trace_stop, (void (*) (void)) tcomplain); *************** update_current_target (void) *** 891,896 **** --- 896,904 ---- de_fault (to_set_circular_trace_buffer, (void (*) (int)) target_ignore); + de_fault (to_set_trace_notes, + (int (*) (char *, char *, char *)) + return_zero); de_fault (to_get_tib_address, (int (*) (ptid_t, CORE_ADDR *)) tcomplain); Index: target.h =================================================================== RCS file: /cvs/src/src/gdb/target.h,v retrieving revision 1.213 diff -p -r1.213 target.h *** target.h 7 Oct 2011 12:06:46 -0000 1.213 --- target.h 17 Oct 2011 15:13:46 -0000 *************** struct target_ops *** 703,708 **** --- 703,711 ---- /* Get the current status of a tracing run. */ int (*to_get_trace_status) (struct trace_status *ts); + void (*to_get_tracepoint_status) (struct breakpoint *tp, + struct uploaded_tp *utp); + /* Stop a trace run. */ void (*to_trace_stop) (void); *************** struct target_ops *** 733,738 **** --- 736,745 ---- void (*to_set_disconnected_tracing) (int val); void (*to_set_circular_trace_buffer) (int val); + /* Add/change textual notes about the trace run, returning 1 if + successful, 0 otherwise. */ + int (*to_set_trace_notes) (char *user, char *notes, char* stopnotes); + /* Return the processor core that thread PTID was last seen on. This information is updated only when: - update_thread_list is called *************** extern int target_search_memory (CORE_AD *** 1486,1491 **** --- 1493,1501 ---- #define target_get_trace_status(ts) \ (*current_target.to_get_trace_status) (ts) + #define target_get_tracepoint_status(tp,utp) \ + (*current_target.to_get_tracepoint_status) (tp, utp) + #define target_trace_stop() \ (*current_target.to_trace_stop) () *************** extern int target_search_memory (CORE_AD *** 1513,1518 **** --- 1523,1531 ---- #define target_set_circular_trace_buffer(val) \ (*current_target.to_set_circular_trace_buffer) (val) + #define target_set_trace_notes(user,notes,stopnotes) \ + (*current_target.to_set_trace_notes) ((user), (notes), (stopnotes)) + #define target_get_tib_address(ptid, addr) \ (*current_target.to_get_tib_address) ((ptid), (addr)) Index: tracepoint.c =================================================================== RCS file: /cvs/src/src/gdb/tracepoint.c,v retrieving revision 1.233 diff -p -r1.233 tracepoint.c *** tracepoint.c 13 Oct 2011 13:06:18 -0000 1.233 --- tracepoint.c 17 Oct 2011 15:13:46 -0000 *************** static int disconnected_tracing; *** 177,182 **** --- 177,194 ---- static int circular_trace_buffer; + /* Textual notes applying to the current and/or future trace runs. */ + + char *trace_user = NULL; + + /* Textual notes applying to the current and/or future trace runs. */ + + char *trace_notes = NULL; + + /* Textual notes applying to the stopping of a trace. */ + + char *trace_stop_notes = NULL; + /* ======= Important command functions: ======= */ static void trace_actions_command (char *, int); static void trace_start_command (char *, int); *************** static char *mem2hex (gdb_byte *, char * *** 198,205 **** static void add_register (struct collection_list *collection, unsigned int regno); - extern void send_disconnected_tracing_value (int value); - static void free_uploaded_tps (struct uploaded_tp **utpp); static void free_uploaded_tsvs (struct uploaded_tsv **utsvp); --- 210,215 ---- *************** add_aexpr (struct collection_list *colle *** 1595,1608 **** void ! start_tracing (void) { VEC(breakpoint_p) *tp_vec = NULL; int ix; struct breakpoint *b; struct trace_state_variable *tsv; int any_enabled = 0, num_to_download = 0; ! tp_vec = all_tracepoints (); /* No point in tracing without any tracepoints... */ --- 1605,1619 ---- void ! start_tracing (char *notes) { VEC(breakpoint_p) *tp_vec = NULL; int ix; struct breakpoint *b; struct trace_state_variable *tsv; int any_enabled = 0, num_to_download = 0; ! int ret; ! tp_vec = all_tracepoints (); /* No point in tracing without any tracepoints... */ *************** start_tracing (void) *** 1676,1681 **** --- 1687,1699 ---- target_set_disconnected_tracing (disconnected_tracing); target_set_circular_trace_buffer (circular_trace_buffer); + if (!notes) + notes = trace_notes; + ret = target_set_trace_notes (trace_user, notes, NULL); + + if (!ret && (trace_user || notes)) + warning ("Target does not support trace user/notes, info ignored"); + /* Now insert traps and begin collecting data. */ target_trace_start (); *************** start_tracing (void) *** 1687,1698 **** clear_traceframe_info (); } ! /* tstart command: ! ! Tell target to clear any previous trace experiment. ! Walk the list of tracepoints, and send them (and their actions) ! to the target. If no errors, ! Tell target to start a new trace experiment. */ static void trace_start_command (char *args, int from_tty) --- 1705,1715 ---- clear_traceframe_info (); } ! /* The tstart command requests the target to start a new trace run. ! The command passes any arguments it has to the target verbatim, as ! an optional "trace note". This is useful as for instance a warning ! to other users if the trace runs disconnected, and you don't want ! anybody else messing with the target. */ static void trace_start_command (char *args, int from_tty) *************** trace_start_command (char *args, int fro *** 1706,1728 **** error (_("New trace run not started.")); } ! start_tracing (); } ! /* tstop command */ static void trace_stop_command (char *args, int from_tty) { if (!current_trace_status ()->running) error (_("Trace is not running.")); ! stop_tracing (); } void ! stop_tracing (void) { target_trace_stop (); /* Should change in response to reply? */ current_trace_status ()->running = 0; } --- 1723,1759 ---- error (_("New trace run not started.")); } ! start_tracing (args); } ! /* The tstop command stops the tracing run. The command passes any ! supplied arguments to the target verbatim as a "stop note"; if the ! target supports trace notes, then it will be reported back as part ! of the trace run's status. */ ! static void trace_stop_command (char *args, int from_tty) { if (!current_trace_status ()->running) error (_("Trace is not running.")); ! stop_tracing (args); } void ! stop_tracing (char *note) { + int ret; + target_trace_stop (); + + if (!note) + note = trace_stop_notes; + ret = target_set_trace_notes (NULL, NULL, note); + + if (!ret && note) + warning ("Target does not support trace notes, note ignored"); + /* Should change in response to reply? */ current_trace_status ()->running = 0; } *************** static void *** 1732,1738 **** trace_status_command (char *args, int from_tty) { struct trace_status *ts = current_trace_status (); ! int status; status = target_get_trace_status (ts); --- 1763,1771 ---- trace_status_command (char *args, int from_tty) { struct trace_status *ts = current_trace_status (); ! int status, ix; ! VEC(breakpoint_p) *tp_vec = NULL; ! struct breakpoint *t; status = target_get_trace_status (ts); *************** trace_status_command (char *args, int fr *** 1763,1769 **** printf_filtered (_("No trace has been run on the target.\n")); break; case tstop_command: ! printf_filtered (_("Trace stopped by a tstop command.\n")); break; case trace_buffer_full: printf_filtered (_("Trace stopped because the buffer was full.\n")); --- 1796,1806 ---- printf_filtered (_("No trace has been run on the target.\n")); break; case tstop_command: ! if (ts->stop_desc) ! printf_filtered (_("Trace stopped by a tstop command (%s).\n"), ! ts->stop_desc); ! else ! printf_filtered (_("Trace stopped by a tstop command.\n")); break; case trace_buffer_full: printf_filtered (_("Trace stopped because the buffer was full.\n")); *************** trace_status_command (char *args, int fr *** 1779,1788 **** if (ts->stopping_tracepoint) printf_filtered (_("Trace stopped by an " "error (%s, tracepoint %d).\n"), ! ts->error_desc, ts->stopping_tracepoint); else printf_filtered (_("Trace stopped by an error (%s).\n"), ! ts->error_desc); break; case trace_stop_reason_unknown: printf_filtered (_("Trace stopped for an unknown reason.\n")); --- 1816,1825 ---- if (ts->stopping_tracepoint) printf_filtered (_("Trace stopped by an " "error (%s, tracepoint %d).\n"), ! ts->stop_desc, ts->stopping_tracepoint); else printf_filtered (_("Trace stopped by an error (%s).\n"), ! ts->stop_desc); break; case trace_stop_reason_unknown: printf_filtered (_("Trace stopped for an unknown reason.\n")); *************** trace_status_command (char *args, int fr *** 1833,1844 **** --- 1870,1895 ---- if (ts->circular_buffer) printf_filtered (_("Trace buffer is circular.\n")); + if (ts->user_name && strlen (ts->user_name) > 0) + printf_filtered (_("Trace user is %s.\n"), ts->user_name); + + if (ts->notes && strlen (ts->notes) > 0) + printf_filtered (_("Trace notes: %s.\n"), ts->notes); + /* Now report on what we're doing with tfind. */ if (traceframe_number >= 0) printf_filtered (_("Looking at trace frame %d, tracepoint %d.\n"), traceframe_number, tracepoint_number); else printf_filtered (_("Not looking at any trace frame.\n")); + + /* Now report any per-tracepoint status available. */ + tp_vec = all_tracepoints (); + + for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++) + target_get_tracepoint_status (t, NULL); + + VEC_free (breakpoint_p, tp_vec); } /* Report the trace status to uiout, in a way suitable for MI, and not *************** trace_status_mi (int on_stop) *** 1921,1927 **** stopping_tracepoint); if (ts->stop_reason == tracepoint_error) ui_out_field_string (uiout, "error-description", ! ts->error_desc); } } } --- 1972,1978 ---- stopping_tracepoint); if (ts->stop_reason == tracepoint_error) ui_out_field_string (uiout, "error-description", ! ts->stop_desc); } } } *************** trace_save (const char *filename, int ta *** 2773,2781 **** (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]); if (ts->stop_reason == tracepoint_error) { ! char *buf = (char *) alloca (strlen (ts->error_desc) * 2 + 1); ! bin2hex ((gdb_byte *) ts->error_desc, buf, 0); fprintf (fp, ":%s", buf); } fprintf (fp, ":%x", ts->stopping_tracepoint); --- 2824,2832 ---- (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]); if (ts->stop_reason == tracepoint_error) { ! char *buf = (char *) alloca (strlen (ts->stop_desc) * 2 + 1); ! bin2hex ((gdb_byte *) ts->stop_desc, buf, 0); fprintf (fp, ":%s", buf); } fprintf (fp, ":%x", ts->stopping_tracepoint); *************** trace_save (const char *filename, int ta *** 2828,2833 **** --- 2879,2887 ---- target_upload_tracepoints (&uploaded_tps); for (utp = uploaded_tps; utp; utp = utp->next) + target_get_tracepoint_status (NULL, utp); + + for (utp = uploaded_tps; utp; utp = utp->next) { fprintf (fp, "tp T%x:%s:%c:%x:%x", utp->number, phex_nz (utp->addr, sizeof (utp->addr)), *************** trace_save (const char *filename, int ta *** 2863,2868 **** --- 2917,2927 ---- buf, MAX_TRACE_UPLOAD); fprintf (fp, "tp Z%s\n", buf); } + fprintf (fp, "tp V%x:%s:%x:%s\n", + utp->number, phex_nz (utp->addr, sizeof (utp->addr)), + utp->hit_count, + phex_nz (utp->traceframe_usage, + sizeof (utp->traceframe_usage))); } free_uploaded_tps (&uploaded_tps); *************** trace_save_command (char *args, int from *** 2933,2949 **** /* Tell the target what to do with an ongoing tracing run if GDB disconnects for some reason. */ - void - send_disconnected_tracing_value (int value) - { - target_set_disconnected_tracing (value); - } - static void set_disconnected_tracing (char *args, int from_tty, struct cmd_list_element *c) { ! send_disconnected_tracing_value (disconnected_tracing); } static void --- 2992,3002 ---- /* Tell the target what to do with an ongoing tracing run if GDB disconnects for some reason. */ static void set_disconnected_tracing (char *args, int from_tty, struct cmd_list_element *c) { ! target_set_disconnected_tracing (disconnected_tracing); } static void *************** set_circular_trace_buffer (char *args, i *** 2953,2958 **** --- 3006,3047 ---- target_set_circular_trace_buffer (circular_trace_buffer); } + static void + set_trace_user (char *args, int from_tty, + struct cmd_list_element *c) + { + int ret; + + ret = target_set_trace_notes (trace_user, NULL, NULL); + + if (!ret) + warning ("Target does not support trace notes, user ignored"); + } + + static void + set_trace_notes (char *args, int from_tty, + struct cmd_list_element *c) + { + int ret; + + ret = target_set_trace_notes (NULL, trace_notes, NULL); + + if (!ret) + warning ("Target does not support trace notes, note ignored"); + } + + static void + set_trace_stop_notes (char *args, int from_tty, + struct cmd_list_element *c) + { + int ret; + + ret = target_set_trace_notes (NULL, NULL, trace_stop_notes); + + if (!ret) + warning ("Target does not support trace notes, stop note ignored"); + } + /* 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 *************** tfile_interp_line (char *line, *** 3523,3542 **** void parse_trace_status (char *line, struct trace_status *ts) { ! char *p = line, *p1, *p2, *p_temp; ULONGEST val; ts->running_known = 1; ts->running = (*p++ == '1'); ts->stop_reason = trace_stop_reason_unknown; ! xfree (ts->error_desc); ! ts->error_desc = NULL; ts->traceframe_count = -1; ts->traceframes_created = -1; ts->buffer_free = -1; ts->buffer_size = -1; ts->disconnected_tracing = 0; ts->circular_buffer = 0; while (*p++) { --- 3612,3636 ---- void parse_trace_status (char *line, struct trace_status *ts) { ! char *p = line, *p1, *p2, *p3, *p_temp; ! int end; ULONGEST val; ts->running_known = 1; ts->running = (*p++ == '1'); ts->stop_reason = trace_stop_reason_unknown; ! xfree (ts->stop_desc); ! ts->stop_desc = NULL; ts->traceframe_count = -1; ts->traceframes_created = -1; ts->buffer_free = -1; ts->buffer_size = -1; ts->disconnected_tracing = 0; ts->circular_buffer = 0; + xfree (ts->user_name); + ts->user_name = NULL; + xfree (ts->notes); + ts->notes = NULL; while (*p++) { *************** parse_trace_status (char *line, struct t *** 3544,3549 **** --- 3638,3646 ---- if (p1 == NULL) error (_("Malformed trace status, at %s\n\ Status line: '%s'\n"), p, line); + p3 = strchr (p, ';'); + if (p3 == NULL) + p3 = p + strlen (p); if (strncmp (p, stop_reason_names[trace_buffer_full], p1 - p) == 0) { p = unpack_varlen_hex (++p1, &val); *************** Status line: '%s'\n"), p, line); *** 3563,3569 **** } else if (strncmp (p, stop_reason_names[tstop_command], p1 - p) == 0) { ! p = unpack_varlen_hex (++p1, &val); ts->stop_reason = tstop_command; } else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0) --- 3660,3681 ---- } else if (strncmp (p, stop_reason_names[tstop_command], p1 - p) == 0) { ! p2 = strchr (++p1, ':'); ! if (!p2 || p2 > p3) ! { ! /*older style*/ ! p2 = p1; ! } ! else if (p2 != p1) ! { ! ts->stop_desc = xmalloc (strlen (line)); ! end = hex2bin (p1, ts->stop_desc, (p2 - p1) / 2); ! ts->stop_desc[end] = '\0'; ! } ! else ! ts->stop_desc = xstrdup (""); ! ! p = unpack_varlen_hex (++p2, &val); ts->stop_reason = tstop_command; } else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0) *************** Status line: '%s'\n"), p, line); *** 3576,3589 **** p2 = strchr (++p1, ':'); if (p2 != p1) { ! int end; ! ! ts->error_desc = xmalloc ((p2 - p1) / 2 + 1); ! end = hex2bin (p1, ts->error_desc, (p2 - p1) / 2); ! ts->error_desc[end] = '\0'; } else ! ts->error_desc = xstrdup (""); p = unpack_varlen_hex (++p2, &val); ts->stopping_tracepoint = val; --- 3688,3699 ---- p2 = strchr (++p1, ':'); if (p2 != p1) { ! ts->stop_desc = xmalloc ((p2 - p1) / 2 + 1); ! end = hex2bin (p1, ts->stop_desc, (p2 - p1) / 2); ! ts->stop_desc[end] = '\0'; } else ! ts->stop_desc = xstrdup (""); p = unpack_varlen_hex (++p2, &val); ts->stopping_tracepoint = val; *************** Status line: '%s'\n"), p, line); *** 3619,3624 **** --- 3729,3760 ---- p = unpack_varlen_hex (++p1, &val); ts->circular_buffer = val; } + else if (strncmp (p, "starttime", p1 - p) == 0) + { + p = unpack_varlen_hex (++p1, &val); + ts->start_time = val; + } + else if (strncmp (p, "stoptime", p1 - p) == 0) + { + p = unpack_varlen_hex (++p1, &val); + ts->stop_time = val; + } + else if (strncmp (p, "username", p1 - p) == 0) + { + ++p1; + ts->user_name = xmalloc (strlen (p) / 2); + end = hex2bin (p1, ts->user_name, (p3 - p1) / 2); + ts->user_name[end] = '\0'; + p = p3; + } + else if (strncmp (p, "notes", p1 - p) == 0) + { + ++p1; + ts->notes = xmalloc (strlen (p) / 2); + end = hex2bin (p1, ts->notes, (p3 - p1) / 2); + ts->notes[end] = '\0'; + p = p3; + } else { /* Silently skip unknown optional info. */ *************** Status line: '%s'\n"), p, line); *** 3632,3637 **** --- 3768,3793 ---- } } + void + parse_tracepoint_status (char *p, struct breakpoint *bp, + struct uploaded_tp *utp) + { + ULONGEST uval; + struct tracepoint *tp = (struct tracepoint *) bp; + + p = unpack_varlen_hex (p, &uval); + if (tp) + tp->base.hit_count += uval; + else + utp->hit_count += uval; + p = unpack_varlen_hex (p + 1, &uval); + if (tp) + tp->traceframe_usage += uval; + else + utp->traceframe_usage += uval; + /* Ignore any extra, allowing for future extensions. */ + } + /* Given a line of text defining a part of a tracepoint, parse it into an "uploaded tracepoint". */ *************** parse_tracepoint_definition (char *line, *** 3733,3738 **** --- 3889,3900 ---- else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0) VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf)); } + else if (piece == 'V') + { + utp = get_uploaded_tp (num, addr, utpp); + + parse_tracepoint_status (p, NULL, utp); + } else { /* Don't error out, the target might be sending us optional *************** tfile_get_trace_status (struct trace_sta *** 3808,3813 **** --- 3970,3982 ---- return -1; } + static void + tfile_get_tracepoint_status (struct breakpoint *tp, struct uploaded_tp *utp) + { + /* Other bits of trace status were collected as part of opening the + trace files, so nothing to do here. */ + } + /* Given the position of a traceframe in the file, figure out what address the frame was collected at. This would normally be the value of a collected PC register, but if not available, we *************** init_tfile_ops (void) *** 4349,4354 **** --- 4518,4524 ---- tfile_ops.to_xfer_partial = tfile_xfer_partial; tfile_ops.to_files_info = tfile_files_info; tfile_ops.to_get_trace_status = tfile_get_trace_status; + tfile_ops.to_get_tracepoint_status = tfile_get_tracepoint_status; tfile_ops.to_trace_find = tfile_trace_find; tfile_ops.to_get_trace_state_variable_value = tfile_get_trace_state_variable_value; *************** up and stopping the trace run."), *** 4972,4977 **** --- 5142,5168 ---- &setlist, &showlist); + add_setshow_string_cmd ("trace-user", class_trace, + &trace_user, _("\ + Set the user name to use for future trace runs"), _("\ + Show the user name to use for future trace runs"), NULL, + set_trace_user, NULL, + &setlist, &showlist); + + add_setshow_string_cmd ("trace-notes", class_trace, + &trace_notes, _("\ + Set notes string to use for future trace runs"), _("\ + Show the notes string to use for future trace runs"), NULL, + set_trace_notes, NULL, + &setlist, &showlist); + + add_setshow_string_cmd ("trace-stop-notes", class_trace, + &trace_stop_notes, _("\ + Set notes string to use for future tstop commands"), _("\ + Show the notes string to use for future tstop commands"), NULL, + set_trace_stop_notes, NULL, + &setlist, &showlist); + init_tfile_ops (); add_target (&tfile_ops); Index: tracepoint.h =================================================================== RCS file: /cvs/src/src/gdb/tracepoint.h,v retrieving revision 1.43 diff -p -r1.43 tracepoint.h *** tracepoint.h 25 Jul 2011 11:24:44 -0000 1.43 --- tracepoint.h 17 Oct 2011 15:13:46 -0000 *************** struct trace_status *** 79,84 **** --- 79,85 ---- /* This is true if the value of the running field is known. */ int running_known; + /* This is true when the trace experiment is actually running. */ int running; enum trace_stop_reason stop_reason; *************** struct trace_status *** 88,96 **** stop. */ int stopping_tracepoint; ! /* If stop_reason is tracepoint_error, this is a human-readable ! string that describes the error that happened on the target. */ ! char *error_desc; /* Number of traceframes currently in the buffer. */ --- 89,98 ---- stop. */ int stopping_tracepoint; ! /* If stop_reason is tstop_command or tracepoint_error, this is a ! human-readable string that describes the reason for the stop in ! more detail. */ ! char *stop_desc; /* Number of traceframes currently in the buffer. */ *************** struct trace_status *** 117,122 **** --- 119,132 ---- target does not report a value, assume 0. */ int circular_buffer; + + char *user_name; + + char *notes; + + LONGEST start_time; + + LONGEST stop_time; }; struct trace_status *current_trace_status (void); *************** struct uploaded_tp *** 154,159 **** --- 164,173 ---- /* List of original strings defining the tracepoint's actions. */ VEC(char_ptr) *cmd_strings; + int hit_count; + + ULONGEST traceframe_usage; + struct uploaded_tp *next; }; *************** extern int encode_source_string (int num *** 226,231 **** --- 240,248 ---- extern void parse_trace_status (char *line, struct trace_status *ts); + extern void parse_tracepoint_status (char *p, struct breakpoint *tp, + struct uploaded_tp *utp); + extern void parse_tracepoint_definition (char *line, struct uploaded_tp **utpp); extern void parse_tsv_definition (char *line, struct uploaded_tsv **utsvp); *************** extern void merge_uploaded_trace_state_v *** 238,245 **** extern void disconnect_tracing (int from_tty); ! extern void start_tracing (void); ! extern void stop_tracing (void); extern void trace_status_mi (int on_stop); --- 255,262 ---- extern void disconnect_tracing (int from_tty); ! extern void start_tracing (char *notes); ! extern void stop_tracing (char *notes); extern void trace_status_mi (int on_stop); Index: doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.878 diff -p -r1.878 gdb.texinfo *** doc/gdb.texinfo 13 Oct 2011 14:50:08 -0000 1.878 --- doc/gdb.texinfo 17 Oct 2011 15:13:47 -0000 *************** Cnt ID Enb Address Wh *** 10753,10772 **** @subsection Starting and Stopping Trace Experiments @table @code ! @kindex tstart @cindex start a new trace experiment @cindex collected data discarded @item tstart ! This command takes no arguments. It starts the trace experiment, and ! begins collecting data. This has the side effect of discarding all ! the data collected in the trace buffer during the previous trace ! experiment. ! @kindex tstop @cindex stop a running trace experiment @item tstop ! This command takes no arguments. It ends the trace experiment, and ! stops collecting data. @strong{Note}: a trace experiment and data collection may stop automatically if any tracepoint's passcount is reached --- 10753,10779 ---- @subsection Starting and Stopping Trace Experiments @table @code ! @kindex tstart [ @var{notes} ] @cindex start a new trace experiment @cindex collected data discarded @item tstart ! This command starts the trace experiment, and begins collecting data. ! It has the side effect of discarding all the data collected in the ! trace buffer during the previous trace experiment. If any arguments ! are supplied, they are taken as a note and stored with the trace ! experiment's state. The notes may be arbitrary text, and are ! especially useful with disconnected tracing in a multi-user context; ! the notes can explain what the trace is doing, supply user contact ! information, and so forth. ! @kindex tstop [ @var{notes} ] @cindex stop a running trace experiment @item tstop ! This command stops the trace experiment. If any arguments are ! supplied, they are recorded with the experiment as a note. This is ! useful if you are stopping a trace started by someone else, for ! instance if the trace is interfering with the system's behavior and ! needs to be stopped quickly. @strong{Note}: a trace experiment and data collection may stop automatically if any tracepoint's passcount is reached *************** for instance if you are looking at frame *** 10870,10875 **** --- 10877,10909 ---- @end table + @table @code + @item set trace-user @var{text} + @kindex set trace-user + + @item show trace-user + @kindex show trace-user + + @item set trace-notes @var{text} + @kindex set trace-notes + Set the trace run's notes. + + @item show trace-notes + @kindex show trace-notes + Show the trace run's notes. + + @item set trace-stop-notes @var{text} + @kindex set trace-stop-notes + Set the trace run's stop notes. The handling of the note is as for + @code{tstop} arguments; the set command is convenient way to fix a + stop note that is mistaken or incomplete. + + @item show trace-stop-notes + @kindex show trace-stop-notes + Show the trace run's stop notes. + + @end table + @node Tracepoint Restrictions @subsection Tracepoint Restrictions *************** the command by a @samp{,}, not a @samp{: *** 34710,34715 **** --- 34744,34751 ---- conventions above. Please don't use this packet as a model for new packets.) + @item QTNotes + @item qTP @item QTSave @item qTsP @item qTsV *************** explanations as one of the optional fiel *** 35268,35275 **** @item tnotrun:0 No trace has been run yet. ! @item tstop:0 ! The trace was stopped by a user-originated stop command. @item tfull:0 The trace stopped because the trace buffer filled up. --- 35304,35314 ---- @item tnotrun:0 No trace has been run yet. ! @item tstop[:@var{text}]:0 ! The trace was stopped by a user-originated stop command. The optional ! @var{text} field is a user-supplied string supplied as part of the ! stop command (for instance, an explanation of why the trace was ! stopped manually). It is hex-encoded. @item tfull:0 The trace stopped because the trace buffer filled up. *************** that the trace run will stop. *** 35325,35330 **** --- 35364,35385 ---- @end table + @item qTP:@var{tp}:@var{addr} + @cindex tracepoint status, remote request + @cindex @samp{qTP} packet + Ask the stub for the current state of tracepoint number @var{tp} at + address @var{addr}. + + Replies: + @table @samp + @item V@var{hits}:@var{usage} + The tracepoint has been hit @var{hits} times so far during the trace + run, and accounts for @var{usage} in the trace buffer. Note that + @code{while-stepping} steps are not counted as separate hits, but the + steps' space consumption is added into the usage number. + + @end table + @item qTV:@var{var} @cindex trace state variable value, remote request @cindex @samp{qTV} packet *************** available. *** 35418,35423 **** --- 35473,35483 ---- This packet directs the target to use a circular trace buffer if @var{value} is 1, or a linear buffer if the value is 0. + @item QTNotes:@r{[}@var{type}:@var{text}@r{]}@r{[};@var{type}:@var{text}@r{]}@dots{} + This packet adds optional textual notes to the trace run. Allowable + types include @code{user}, @code{notes}, and @code{tstop}, the + @var{text} fields are arbitrary strings, hex-encoded. + @end table @subsection Relocate instruction reply packet Index: gdbserver/tracepoint.c =================================================================== RCS file: /cvs/src/src/gdb/gdbserver/tracepoint.c,v retrieving revision 1.27 diff -p -r1.27 tracepoint.c *** gdbserver/tracepoint.c 15 Sep 2011 22:54:13 -0000 1.27 --- gdbserver/tracepoint.c 17 Oct 2011 15:13:47 -0000 *************** struct tracepoint *** 623,628 **** --- 623,631 ---- Note that while-stepping steps are not counted as "hits". */ long hit_count; + /* Cached sum of the sizes of traceframes created by this point. */ + long traceframe_usage; + CORE_ADDR compiled_cond; /* Link to the next tracepoint in the list. */ *************** static const char *tracing_stop_reason = *** 1129,1134 **** --- 1132,1150 ---- static int tracing_stop_tpnum; + /* 64-bit timestamps for the trace run's start and finish. */ + + long long start_time; + long long stop_time; + + /* The (optional) name of the user that started the run. */ + + char *tracing_user_name; + + /* User-supplied text describing the run for the benefit of other users. */ + + char *tracing_notes; + #endif /* Functions local to this file. */ *************** static void do_action_at_tracepoint (str *** 1244,1249 **** --- 1260,1267 ---- static struct tracepoint *fast_tracepoint_from_ipa_tpoint_address (CORE_ADDR); #endif + static LONGEST get_timestamp (void); + #if defined(__GNUC__) # define memory_barrier() asm volatile ("" : : : "memory") #else *************** cmd_qtstart (char *packet) *** 2788,2793 **** --- 2806,2812 ---- { /* Ensure all the hit counts start at zero. */ tpoint->hit_count = 0; + tpoint->traceframe_usage = 0; if (tpoint->type == trap_tracepoint) { *************** cmd_qtstart (char *packet) *** 2912,2917 **** --- 2931,2937 ---- trace_buffer_is_full = 0; expr_eval_result = expr_eval_no_error; error_tracepoint = NULL; + start_time = get_timestamp (); /* Tracing is now active, hits will now start being logged. */ tracing = 1; *************** stop_tracing (void) *** 2981,2986 **** --- 3001,3007 ---- fatal ("Error clearing tracing variable in lib"); } + stop_time = get_timestamp (); tracing_stop_reason = "t???"; tracing_stop_tpnum = 0; if (stopping_tracepoint) *************** cmd_qtstatus (char *packet) *** 3162,3167 **** --- 3183,3201 ---- { char *stop_reason_rsp = NULL; + char *buf1, *buf2, *str; + int slen; + + str = (tracing_user_name ? tracing_user_name : ""); + slen = strlen (str); + buf1 = (char *) alloca (slen * 2 + 1); + hexify (buf1, str, slen); + + str = (tracing_notes ? tracing_notes : ""); + slen = strlen (str); + buf2 = (char *) alloca (slen * 2 + 1); + hexify (buf2, str, slen); + trace_debug ("Returning trace status as %d, stop reason %s", tracing, tracing_stop_reason); *************** cmd_qtstatus (char *packet) *** 3199,3211 **** "tframes:%x;tcreated:%x;" "tfree:%x;tsize:%s;" "circular:%d;" ! "disconn:%d", tracing ? 1 : 0, stop_reason_rsp, tracing_stop_tpnum, traceframe_count, traceframes_created, free_space (), phex_nz (trace_buffer_hi - trace_buffer_lo, 0), circular_trace_buffer, ! disconnected_tracing); } /* State variables to help return all the tracepoint bits. */ --- 3233,3276 ---- "tframes:%x;tcreated:%x;" "tfree:%x;tsize:%s;" "circular:%d;" ! "disconn:%d" ! "starttime:%llx;stoptime:%llx;" ! "username:%s:;notes:%s:", tracing ? 1 : 0, stop_reason_rsp, tracing_stop_tpnum, traceframe_count, traceframes_created, free_space (), phex_nz (trace_buffer_hi - trace_buffer_lo, 0), circular_trace_buffer, ! disconnected_tracing, ! start_time, stop_time, ! buf1, buf2); ! } ! ! static void ! cmd_qtp (char *own_buf) ! { ! ULONGEST num, addr; ! struct tracepoint *tpoint; ! char *packet = own_buf; ! ! packet += strlen ("qTP:"); ! ! packet = unpack_varlen_hex (packet, &num); ! ++packet; /* skip a colon */ ! packet = unpack_varlen_hex (packet, &addr); ! ! /* See if we already have this tracepoint. */ ! tpoint = find_tracepoint (num, addr); ! ! if (!tpoint) ! { ! trace_debug ("Tracepoint error: tracepoint %d at 0x%s not found", ! (int) num, paddress (addr)); ! write_enn (own_buf); ! return; ! } ! ! sprintf (own_buf, "V%lx:%lx", tpoint->hit_count, tpoint->traceframe_usage); } /* State variables to help return all the tracepoint bits. */ *************** cmd_bigqtbuffer (char *own_buf) *** 3510,3515 **** --- 3575,3636 ---- write_enn (own_buf); } + static void + cmd_qtnotes (char *own_buf) + { + size_t nbytes; + char *saved, *user, *notes, *tstop; + char *packet = own_buf; + + packet += strlen ("QTNotes:"); + + while (*packet) + { + if (strncmp ("user:", packet, strlen ("user:")) == 0) + { + packet += strlen ("user:"); + saved = packet; + packet = strchr (packet, ';'); + nbytes = (packet - saved) / 2; + user = xmalloc (nbytes + 1); + nbytes = unhexify (user, saved, nbytes); + user[nbytes] = '\0'; + ++packet; /* skip the semicolon */ + trace_debug ("User is '%s'", user); + tracing_user_name = user; + } + else if (strncmp ("notes:", packet, strlen ("notes:")) == 0) + { + packet += strlen ("notes:"); + saved = packet; + packet = strchr (packet, ';'); + nbytes = (packet - saved) / 2; + notes = xmalloc (nbytes + 1); + nbytes = unhexify (notes, saved, nbytes); + notes[nbytes] = '\0'; + ++packet; /* skip the semicolon */ + trace_debug ("Notes is '%s'", notes); + tracing_notes = notes; + } + else if (strncmp ("tstop:", packet, strlen ("tstop:")) == 0) + { + saved = packet; + packet = strchr (packet, ';'); + nbytes = (packet - saved) / 2; + tstop = xmalloc (nbytes + 1); + nbytes = unhexify (tstop, saved, nbytes); + tstop[nbytes] = '\0'; + ++packet; /* skip the semicolon */ + trace_debug ("tstop reason is '%s'", tstop); + tracing_stop_reason = tstop; + } + else + break; + } + + write_ok (own_buf); + } + int handle_tracepoint_general_set (char *packet) { *************** handle_tracepoint_general_set (char *pac *** 3574,3579 **** --- 3695,3705 ---- cmd_bigqtbuffer (packet); return 1; } + else if (strncmp ("QTNotes:", packet, strlen ("QTNotes:")) == 0) + { + cmd_qtnotes (packet); + return 1; + } return 0; } *************** handle_tracepoint_query (char *packet) *** 3586,3591 **** --- 3712,3722 ---- cmd_qtstatus (packet); return 1; } + else if (strncmp ("qTP:", packet, strlen ("qTP:")) == 0) + { + cmd_qtp (packet); + return 1; + } else if (strcmp ("qTfP", packet) == 0) { cmd_qtfp (packet); *************** initialize_tracepoint_ftlib (void) *** 7635,7641 **** #endif /* IN_PROCESS_AGENT */ static LONGEST ! tsv_get_timestamp (void) { struct timeval tv; --- 7766,7772 ---- #endif /* IN_PROCESS_AGENT */ static LONGEST ! get_timestamp (void) { struct timeval tv; *************** initialize_tracepoint (void) *** 7659,7665 **** variable numbered 1, it will be renumbered.) */ create_trace_state_variable (1, 0); set_trace_state_variable_name (1, "trace_timestamp"); ! set_trace_state_variable_getter (1, tsv_get_timestamp); #ifdef IN_PROCESS_AGENT { --- 7790,7796 ---- variable numbered 1, it will be renumbered.) */ create_trace_state_variable (1, 0); set_trace_state_variable_name (1, "trace_timestamp"); ! set_trace_state_variable_getter (1, get_timestamp); #ifdef IN_PROCESS_AGENT { Index: mi/mi-main.c =================================================================== RCS file: /cvs/src/src/gdb/mi/mi-main.c,v retrieving revision 1.207 diff -p -r1.207 mi-main.c *** mi/mi-main.c 3 Oct 2011 21:38:31 -0000 1.207 --- mi/mi-main.c 17 Oct 2011 15:13:48 -0000 *************** mi_cmd_trace_save (char *command, char * *** 2490,2496 **** void mi_cmd_trace_start (char *command, char **argv, int argc) { ! start_tracing (); } void --- 2490,2496 ---- void mi_cmd_trace_start (char *command, char **argv, int argc) { ! start_tracing (NULL); } void *************** mi_cmd_trace_status (char *command, char *** 2502,2508 **** void mi_cmd_trace_stop (char *command, char **argv, int argc) { ! stop_tracing (); trace_status_mi (1); } --- 2502,2508 ---- void mi_cmd_trace_stop (char *command, char **argv, int argc) { ! stop_tracing (NULL); trace_status_mi (1); }