aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>2010-01-07 19:17:46 +0000
committerStan Shebs <shebs@codesourcery.com>2010-01-07 19:17:46 +0000
commit35b1e5cca081f63a45e2d6bbc90010e553f7c5c8 (patch)
tree8218989127b1070c5b6c3dde0eff2b18f3623774
parent3f08eb35896e102a28d1249ca197c037c4efa9de (diff)
downloadgdb-35b1e5cca081f63a45e2d6bbc90010e553f7c5c8.zip
gdb-35b1e5cca081f63a45e2d6bbc90010e553f7c5c8.tar.gz
gdb-35b1e5cca081f63a45e2d6bbc90010e553f7c5c8.tar.bz2
Make tracepoint operations go through target vector.
* target.h (enum trace_find_type): New enum. (struct target_ops): New fields to_trace_init, to_download_tracepoint, to_download_trace_state_variable, to_trace_set_readonly_regions, to_trace_start, to_get_trace_status, to_trace_stop, to_trace_find, to_get_trace_state_variable_value, to_set_disconnected_tracing. (target_trace_init): New macro. (target_download_tracepoint): New macro. (target_download_trace_state_variable): New macro. (target_trace_start): New macro. (target_trace_set_readonly_regions): New macro. (target_get_trace_status): New macro. (target_trace_stop): New macro. (target_trace_find): New macro. (target_get_trace_state_variable_value): New macro. (target_set_disconnected_tracing): New macro. * target.c (update_current_target): Inherit and set defaults for tracepoint operations. * tracepoint.c (default_collect): Make globally visible. (target_is_remote): Remove, along with all calls. (tvariables_info): Call target_get_trace_state_variable_value. (remote_set_transparent_ranges): Remove. (trace_start_command): Call target_trace_init, target_download_tracepoint, etc. (download_tracepoint): Remove. (trace_stop_command): Simplify. (stop_tracing): Call target_trace_stop. (get_trace_status): Call target_get_trace_status. (trace_status_command): Add case for targets that cannot trace. (finish_tfind_command): Change to take numerical arguments, call target_trace_find. (trace_find_command): Update call to finish_tfind_command. (trace_find_pc_command): Ditto. (trace_find_tracepoint_command): Ditto. (trace_find_line_command): Ditto. (trace_find_range_command): Ditto. (trace_find_outside_command): Ditto. (set_disconnected_tracing_value): Call target_set_disconnected_tracing. * remote.c: Add protocol encoding bits from tracepoint.c. (trace_error): Move from tracepoint.c. (remote_get_noisy_reply): Ditto. (free_actions_list_cleanup_wrapper): Ditto. (free_actions_list): Ditto. (remote_trace_init): New function. (remote_download_tracepoint): New function. (remote_download_trace_state_variable): New function. (remote_trace_set_readonly_regions): New function. (remote_trace_start): New function. (remote_get_trace_status): New function. (remote_trace_stop): New function. (remote_trace_find): New function. (remote_download_trace_state_variable): New function. (remote_set_disconnected_tracing): New function. (init_remote_ops): Add tracepoint operations.
-rw-r--r--gdb/ChangeLog57
-rw-r--r--gdb/remote.c396
-rw-r--r--gdb/target.c40
-rw-r--r--gdb/target.h86
-rw-r--r--gdb/tracepoint.c920
-rw-r--r--gdb/tracepoint.h2
6 files changed, 846 insertions, 655 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6d3938d..3430364 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,62 @@
2010-01-07 Stan Shebs <stan@codesourcery.com>
+ Make tracepoint operations go through target vector.
+ * target.h (enum trace_find_type): New enum.
+ (struct target_ops): New fields to_trace_init,
+ to_download_tracepoint, to_download_trace_state_variable,
+ to_trace_set_readonly_regions, to_trace_start, to_get_trace_status,
+ to_trace_stop, to_trace_find, to_get_trace_state_variable_value,
+ to_set_disconnected_tracing.
+ (target_trace_init): New macro.
+ (target_download_tracepoint): New macro.
+ (target_download_trace_state_variable): New macro.
+ (target_trace_start): New macro.
+ (target_trace_set_readonly_regions): New macro.
+ (target_get_trace_status): New macro.
+ (target_trace_stop): New macro.
+ (target_trace_find): New macro.
+ (target_get_trace_state_variable_value): New macro.
+ (target_set_disconnected_tracing): New macro.
+ * target.c (update_current_target): Inherit and set defaults for
+ tracepoint operations.
+ * tracepoint.c (default_collect): Make globally visible.
+ (target_is_remote): Remove, along with all calls.
+ (tvariables_info): Call target_get_trace_state_variable_value.
+ (remote_set_transparent_ranges): Remove.
+ (trace_start_command): Call target_trace_init,
+ target_download_tracepoint, etc.
+ (download_tracepoint): Remove.
+ (trace_stop_command): Simplify.
+ (stop_tracing): Call target_trace_stop.
+ (get_trace_status): Call target_get_trace_status.
+ (trace_status_command): Add case for targets that cannot trace.
+ (finish_tfind_command): Change to take numerical arguments, call
+ target_trace_find.
+ (trace_find_command): Update call to finish_tfind_command.
+ (trace_find_pc_command): Ditto.
+ (trace_find_tracepoint_command): Ditto.
+ (trace_find_line_command): Ditto.
+ (trace_find_range_command): Ditto.
+ (trace_find_outside_command): Ditto.
+ (set_disconnected_tracing_value): Call
+ target_set_disconnected_tracing.
+ * remote.c: Add protocol encoding bits from tracepoint.c.
+ (trace_error): Move from tracepoint.c.
+ (remote_get_noisy_reply): Ditto.
+ (free_actions_list_cleanup_wrapper): Ditto.
+ (free_actions_list): Ditto.
+ (remote_trace_init): New function.
+ (remote_download_tracepoint): New function.
+ (remote_download_trace_state_variable): New function.
+ (remote_trace_set_readonly_regions): New function.
+ (remote_trace_start): New function.
+ (remote_get_trace_status): New function.
+ (remote_trace_stop): New function.
+ (remote_trace_find): New function.
+ (remote_download_trace_state_variable): New function.
+ (remote_set_disconnected_tracing): New function.
+ (init_remote_ops): Add tracepoint operations.
+
* tracepoint.c (trace_dump_command): Don't decr_pc_after_break.
2010-01-07 Tristan Gingold <gingold@adacore.com>
diff --git a/gdb/remote.c b/gdb/remote.c
index 262b97f..9c50f7e 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -63,6 +63,17 @@
#include "memory-map.h"
+#include "tracepoint.h"
+#include "ax.h"
+#include "ax-gdb.h"
+
+/* temp hacks for tracepoint encoding migration */
+static char *target_buf;
+static long target_buf_size;
+/*static*/ void
+encode_actions (struct breakpoint *t, char ***tdp_actions,
+ char ***stepping_actions);
+
/* The size to align memory write packets, when practical. The protocol
does not guarantee any alignment, and gdb will generate short
writes and unaligned writes, but even as a best-effort attempt this
@@ -368,6 +379,52 @@ struct remote_arch_state
long remote_packet_size;
};
+long sizeof_pkt = 2000;
+
+/* Utility: generate error from an incoming stub packet. */
+static void
+trace_error (char *buf)
+{
+ if (*buf++ != 'E')
+ return; /* not an error msg */
+ switch (*buf)
+ {
+ case '1': /* malformed packet error */
+ if (*++buf == '0') /* general case: */
+ error (_("remote.c: error in outgoing packet."));
+ else
+ error (_("remote.c: error in outgoing packet at field #%ld."),
+ strtol (buf, NULL, 16));
+ case '2':
+ error (_("trace API error 0x%s."), ++buf);
+ default:
+ error (_("Target returns error code '%s'."), buf);
+ }
+}
+
+/* Utility: wait for reply from stub, while accepting "O" packets. */
+static char *
+remote_get_noisy_reply (char **buf_p,
+ long *sizeof_buf)
+{
+ do /* Loop on reply from remote stub. */
+ {
+ char *buf;
+ QUIT; /* allow user to bail out with ^C */
+ getpkt (buf_p, sizeof_buf, 0);
+ buf = *buf_p;
+ if (buf[0] == 0)
+ error (_("Target does not support this command."));
+ else if (buf[0] == 'E')
+ trace_error (buf);
+ else if (buf[0] == 'O' &&
+ buf[1] != 'K')
+ remote_console_output (buf + 1); /* 'O' message from stub */
+ else
+ return buf; /* here's the actual reply */
+ }
+ while (1);
+}
/* Handle for retreving the remote protocol data from gdbarch. */
static struct gdbarch_data *remote_gdbarch_data_handle;
@@ -8943,6 +9000,331 @@ remote_supports_fast_tracepoints (void)
}
static void
+remote_trace_init ()
+{
+ putpkt ("QTinit");
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Target does not support this command."));
+}
+
+static void free_actions_list (char **actions_list);
+static void free_actions_list_cleanup_wrapper (void *);
+static void
+free_actions_list_cleanup_wrapper (void *al)
+{
+ free_actions_list (al);
+}
+
+static void
+free_actions_list (char **actions_list)
+{
+ int ndx;
+
+ if (actions_list == 0)
+ return;
+
+ for (ndx = 0; actions_list[ndx]; ndx++)
+ xfree (actions_list[ndx]);
+
+ xfree (actions_list);
+}
+
+static void
+remote_download_tracepoint (struct breakpoint *t)
+{
+ CORE_ADDR tpaddr;
+ char tmp[40];
+ char buf[2048];
+ char **tdp_actions;
+ char **stepping_actions;
+ int ndx;
+ struct cleanup *old_chain = NULL;
+ struct agent_expr *aexpr;
+ struct cleanup *aexpr_chain = NULL;
+ char *pkt;
+
+ encode_actions (t, &tdp_actions, &stepping_actions);
+ old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
+ tdp_actions);
+ (void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions);
+
+ tpaddr = t->loc->address;
+ sprintf_vma (tmp, (t->loc ? tpaddr : 0));
+ sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number,
+ tmp, /* address */
+ (t->enable_state == bp_enabled ? 'E' : 'D'),
+ t->step_count, t->pass_count);
+ /* Fast tracepoints are mostly handled by the target, but we can
+ tell the target how big of an instruction block should be moved
+ around. */
+ if (t->type == bp_fast_tracepoint)
+ {
+ /* Only test for support at download time; we may not know
+ target capabilities at definition time. */
+ if (remote_supports_fast_tracepoints ())
+ {
+ int isize;
+
+ if (gdbarch_fast_tracepoint_valid_at (target_gdbarch,
+ tpaddr, &isize, NULL))
+ sprintf (buf + strlen (buf), ":F%x", isize);
+ else
+ /* If it passed validation at definition but fails now,
+ something is very wrong. */
+ internal_error (__FILE__, __LINE__,
+ "Fast tracepoint not valid during download");
+ }
+ else
+ /* Fast tracepoints are functionally identical to regular
+ tracepoints, so don't take lack of support as a reason to
+ give up on the trace run. */
+ warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
+ }
+ /* If the tracepoint has a conditional, make it into an agent
+ expression and append to the definition. */
+ if (t->loc->cond)
+ {
+ /* Only test support at download time, we may not know target
+ capabilities at definition time. */
+ if (remote_supports_cond_tracepoints ())
+ {
+ aexpr = gen_eval_for_expr (t->loc->address, t->loc->cond);
+ aexpr_chain = make_cleanup_free_agent_expr (aexpr);
+ sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
+ pkt = buf + strlen (buf);
+ for (ndx = 0; ndx < aexpr->len; ++ndx)
+ pkt = pack_hex_byte (pkt, aexpr->buf[ndx]);
+ *pkt = '\0';
+ do_cleanups (aexpr_chain);
+ }
+ else
+ warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
+ }
+
+ if (t->actions || *default_collect)
+ strcat (buf, "-");
+ putpkt (buf);
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Target does not support tracepoints."));
+
+ if (!t->actions && !*default_collect)
+ return;
+
+ /* do_single_steps (t); */
+ if (tdp_actions)
+ {
+ for (ndx = 0; tdp_actions[ndx]; ndx++)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ sprintf (buf, "QTDP:-%x:%s:%s%c",
+ t->number, tmp, /* address */
+ tdp_actions[ndx],
+ ((tdp_actions[ndx + 1] || stepping_actions)
+ ? '-' : 0));
+ putpkt (buf);
+ remote_get_noisy_reply (&target_buf,
+ &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Error on target while setting tracepoints."));
+ }
+ }
+ if (stepping_actions)
+ {
+ for (ndx = 0; stepping_actions[ndx]; ndx++)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ sprintf (buf, "QTDP:-%x:%s:%s%s%s",
+ t->number, tmp, /* address */
+ ((ndx == 0) ? "S" : ""),
+ stepping_actions[ndx],
+ (stepping_actions[ndx + 1] ? "-" : ""));
+ putpkt (buf);
+ remote_get_noisy_reply (&target_buf,
+ &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Error on target while setting tracepoints."));
+ }
+ }
+ do_cleanups (old_chain);
+ return;
+}
+
+static void
+remote_download_trace_state_variable (struct trace_state_variable *tsv)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ sprintf (rs->buf, "QTDV:%x:%s",
+ tsv->number, phex ((ULONGEST) tsv->initial_value, 8));
+ putpkt (rs->buf);
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+}
+
+static void
+remote_trace_set_readonly_regions ()
+{
+ asection *s;
+ bfd_size_type size;
+ bfd_vma lma;
+ int anysecs = 0;
+
+ if (!exec_bfd)
+ return; /* No information to give. */
+
+ strcpy (target_buf, "QTro");
+ for (s = exec_bfd->sections; s; s = s->next)
+ {
+ char tmp1[40], tmp2[40];
+
+ if ((s->flags & SEC_LOAD) == 0 ||
+ /* (s->flags & SEC_CODE) == 0 || */
+ (s->flags & SEC_READONLY) == 0)
+ continue;
+
+ anysecs = 1;
+ lma = s->lma;
+ size = bfd_get_section_size (s);
+ sprintf_vma (tmp1, lma);
+ sprintf_vma (tmp2, lma + size);
+ sprintf (target_buf + strlen (target_buf),
+ ":%s,%s", tmp1, tmp2);
+ }
+ if (anysecs)
+ {
+ putpkt (target_buf);
+ getpkt (&target_buf, &target_buf_size, 0);
+ }
+}
+
+static void
+remote_trace_start ()
+{
+ putpkt ("QTStart");
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Bogus reply from target: %s"), target_buf);
+}
+
+static int
+remote_get_trace_status (int *stop_reason)
+{
+ 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);
+
+ return (target_buf[1] == '1');
+}
+
+static void
+remote_trace_stop ()
+{
+ putpkt ("QTStop");
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Bogus reply from target: %s"), target_buf);
+}
+
+static int
+remote_trace_find (enum trace_find_type type, int num,
+ ULONGEST addr1, ULONGEST addr2,
+ int *tpp)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p, *reply;
+ int target_frameno = -1, target_tracept = -1;
+
+ p = rs->buf;
+ strcpy (p, "QTFrame:");
+ p = strchr (p, '\0');
+ switch (type)
+ {
+ case tfind_number:
+ sprintf (p, "%x", num);
+ break;
+ case tfind_pc:
+ sprintf (p, "pc:%s", paddress (target_gdbarch, addr1));
+ break;
+ case tfind_tp:
+ sprintf (p, "tdp:%x", num);
+ break;
+ case tfind_range:
+ sprintf (p, "range:%s:%s", paddress (target_gdbarch, addr1), paddress (target_gdbarch, addr2));
+ break;
+ case tfind_outside:
+ sprintf (p, "outside:%s:%s", paddress (target_gdbarch, addr1), paddress (target_gdbarch, addr2));
+ break;
+ default:
+ error ("Unknown trace find type %d", type);
+ }
+
+ putpkt (rs->buf);
+ reply = remote_get_noisy_reply (&(rs->buf), &sizeof_pkt);
+
+ while (reply && *reply)
+ switch (*reply)
+ {
+ case 'F':
+ if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
+ error (_("Target failed to find requested trace frame."));
+ break;
+ case 'T':
+ if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
+ error (_("Target failed to find requested trace frame."));
+ break;
+ case 'O': /* "OK"? */
+ if (reply[1] == 'K' && reply[2] == '\0')
+ reply += 2;
+ else
+ error (_("Bogus reply from target: %s"), reply);
+ break;
+ default:
+ error (_("Bogus reply from target: %s"), reply);
+ }
+ if (tpp)
+ *tpp = target_tracept;
+ return target_frameno;
+}
+
+static int
+remote_get_trace_state_variable_value (int tsvnum, LONGEST *val)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *reply;
+ ULONGEST uval;
+
+ sprintf (rs->buf, "qTV:%x", tsvnum);
+ putpkt (rs->buf);
+ reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (reply && *reply)
+ {
+ if (*reply == 'V')
+ {
+ unpack_varlen_hex (reply + 1, &uval);
+ *val = (LONGEST) uval;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+remote_set_disconnected_tracing (int val)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ sprintf (rs->buf, "QTDisconnected:%x", val);
+ putpkt (rs->buf);
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ error (_("Target does not support this command."));
+}
+
+static void
init_remote_ops (void)
{
remote_ops.to_shortname = "remote";
@@ -9005,6 +9387,16 @@ 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_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_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_trace_stop = remote_trace_stop;
+ remote_ops.to_trace_find = remote_trace_find;
+ remote_ops.to_get_trace_state_variable_value = remote_get_trace_state_variable_value;
+ remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing;
}
/* Set up the extended remote vector by making a copy of the standard
@@ -9227,7 +9619,6 @@ remote_get_tracing_state (struct remote_state *rs)
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)
@@ -9646,4 +10037,7 @@ Show the remote pathname for \"run\""), NULL, NULL, NULL,
magic_null_ptid = ptid_build (42000, 1, -1);
not_sent_ptid = ptid_build (42000, 1, -2);
any_thread_ptid = ptid_build (42000, 1, 0);
+
+ target_buf_size = 2048;
+ target_buf = xmalloc (target_buf_size);
}
diff --git a/gdb/target.c b/gdb/target.c
index 38cd508..25a2cd7 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -685,6 +685,16 @@ 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_trace_init, t);
+ INHERIT (to_download_tracepoint, t);
+ INHERIT (to_download_trace_state_variable, t);
+ INHERIT (to_trace_set_readonly_regions, t);
+ INHERIT (to_trace_start, t);
+ INHERIT (to_get_trace_status, t);
+ INHERIT (to_trace_stop, t);
+ INHERIT (to_trace_find, t);
+ INHERIT (to_get_trace_state_variable_value, t);
+ INHERIT (to_set_disconnected_tracing, t);
INHERIT (to_magic, t);
/* Do not inherit to_memory_map. */
/* Do not inherit to_flash_erase. */
@@ -833,6 +843,36 @@ update_current_target (void)
de_fault (to_supports_multi_process,
(int (*) (void))
return_zero);
+ de_fault (to_trace_init,
+ (void (*) (void))
+ tcomplain);
+ de_fault (to_download_tracepoint,
+ (void (*) (struct breakpoint *))
+ tcomplain);
+ de_fault (to_download_trace_state_variable,
+ (void (*) (struct trace_state_variable *))
+ tcomplain);
+ de_fault (to_trace_set_readonly_regions,
+ (void (*) (void))
+ tcomplain);
+ de_fault (to_trace_start,
+ (void (*) (void))
+ tcomplain);
+ de_fault (to_get_trace_status,
+ (int (*) (int *))
+ return_minus_one);
+ de_fault (to_trace_stop,
+ (void (*) (void))
+ tcomplain);
+ de_fault (to_trace_find,
+ (int (*) (enum trace_find_type, int, ULONGEST, ULONGEST, int *))
+ return_zero);
+ de_fault (to_get_trace_state_variable_value,
+ (int (*) (int, LONGEST *))
+ return_zero);
+ de_fault (to_set_disconnected_tracing,
+ (void (*) (int))
+ tcomplain);
#undef de_fault
/* Finally, position the target-stack beneath the squashed
diff --git a/gdb/target.h b/gdb/target.h
index 9a89b93..20cbe29 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -31,6 +31,7 @@ struct target_ops;
struct bp_target_info;
struct regcache;
struct target_section_table;
+struct trace_state_variable;
/* This include file defines the interface between the main part
of the debugger, and the part which is target-specific, or
@@ -258,6 +259,18 @@ enum target_object
/* Possible future objects: TARGET_OBJECT_FILE, ... */
};
+/* Enumeration of the kinds of traceframe searches that a target may
+ be able to perform. */
+
+enum trace_find_type
+ {
+ tfind_number,
+ tfind_pc,
+ tfind_tp,
+ tfind_range,
+ tfind_outside,
+ };
+
/* Request that OPS transfer up to LEN 8-bit bytes of the target's
OBJECT. The OFFSET, for a seekable object, specifies the
starting point. The ANNEX can be used to provide additional
@@ -597,6 +610,47 @@ struct target_ops
struct address_space *(*to_thread_address_space) (struct target_ops *,
ptid_t);
+ /* Tracepoint-related operations. */
+
+ /* Prepare the target for a tracing run. */
+ void (*to_trace_init) (void);
+
+ /* Send full details of a tracepoint to the target. */
+ void (*to_download_tracepoint) (struct breakpoint *t);
+
+ /* Send full details of a trace state variable to the target. */
+ void (*to_download_trace_state_variable) (struct trace_state_variable *tsv);
+
+ /* 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. */
+ void (*to_trace_set_readonly_regions) (void);
+
+ /* Start a trace run. */
+ void (*to_trace_start) (void);
+
+ /* Get the current status of a tracing run. */
+ int (*to_get_trace_status) (int *stop_reason);
+
+ /* Stop a trace run. */
+ void (*to_trace_stop) (void);
+
+ /* Ask the target to find a trace frame of the given type TYPE,
+ using NUM, ADDR1, and ADDR2 as search parameters. Returns the
+ number of the trace frame, and also the tracepoint number at
+ TPP. */
+ int (*to_trace_find) (enum trace_find_type type, int num,
+ ULONGEST addr1, ULONGEST addr2, int *tpp);
+
+ /* Get the value of the trace state variable number TSV, returning
+ 1 if the value is known and writing the value itself into the
+ location pointed to by VAL, else returning 0. */
+ int (*to_get_trace_state_variable_value) (int tsv, LONGEST *val);
+
+ /* Set the target's tracing behavior in response to unexpected
+ disconnection - set VAL to 1 to keep tracing, 0 to stop. */
+ void (*to_set_disconnected_tracing) (int val);
+
int to_magic;
/* Need sub-structure for target machine related rather than comm related?
*/
@@ -1238,6 +1292,38 @@ extern int target_search_memory (CORE_ADDR start_addr,
ULONGEST pattern_len,
CORE_ADDR *found_addrp);
+/* Tracepoint-related operations. */
+
+#define target_trace_init() \
+ (*current_target.to_trace_init) ()
+
+#define target_download_tracepoint(t) \
+ (*current_target.to_download_tracepoint) (t)
+
+#define target_download_trace_state_variable(tsv) \
+ (*current_target.to_download_trace_state_variable) (tsv)
+
+#define target_trace_start() \
+ (*current_target.to_trace_start) ()
+
+#define target_trace_set_readonly_regions() \
+ (*current_target.to_trace_set_readonly_regions) ()
+
+#define target_get_trace_status(stop_reason) \
+ (*current_target.to_get_trace_status) (stop_reason)
+
+#define target_trace_stop() \
+ (*current_target.to_trace_stop) ()
+
+#define target_trace_find(type,num,addr1,addr2,tpp) \
+ (*current_target.to_trace_find) ((type), (num), (addr1), (addr2), (tpp))
+
+#define target_get_trace_state_variable_value(tsv,val) \
+ (*current_target.to_get_trace_state_variable_value) ((tsv), (val))
+
+#define target_set_disconnected_tracing(val) \
+ (*current_target.to_set_disconnected_tracing) (val)
+
/* Command logging facility. */
#define target_log_command(p) \
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 5d19934..0dfe23c 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -32,10 +32,6 @@
#include "inferior.h"
#include "breakpoint.h"
#include "tracepoint.h"
-#include "remote.h"
-extern int remote_supports_cond_tracepoints (void);
-extern int remote_supports_fast_tracepoints (void);
-extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
#include "linespec.h"
#include "regcache.h"
#include "completer.h"
@@ -46,6 +42,7 @@ extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
#include "valprint.h"
#include "gdbcore.h"
#include "objfiles.h"
+#include "filenames.h"
#include "ax.h"
#include "ax-gdb.h"
@@ -144,13 +141,10 @@ static struct symtab_and_line traceframe_sal;
static struct cmd_list_element *tfindlist;
/* List of expressions to collect by default at each tracepoint hit. */
-static char *default_collect = "";
+char *default_collect = "";
static int disconnected_tracing;
-static char *target_buf;
-static long target_buf_size;
-
/* ======= Important command functions: ======= */
static void trace_actions_command (char *, int);
static void trace_start_command (char *, int);
@@ -173,70 +167,11 @@ static char *mem2hex (gdb_byte *, char *, int);
static void add_register (struct collection_list *collection,
unsigned int regno);
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" */
-static int
-target_is_remote (void)
-{
- if (current_target.to_shortname &&
- (strcmp (current_target.to_shortname, "remote") == 0
- || strcmp (current_target.to_shortname, "extended-remote") == 0))
- return 1;
- else
- return 0;
-}
-
-/* Utility: generate error from an incoming stub packet. */
-static void
-trace_error (char *buf)
-{
- if (*buf++ != 'E')
- return; /* not an error msg */
- switch (*buf)
- {
- case '1': /* malformed packet error */
- if (*++buf == '0') /* general case: */
- error (_("tracepoint.c: error in outgoing packet."));
- else
- error (_("tracepoint.c: error in outgoing packet at field #%ld."),
- strtol (buf, NULL, 16));
- case '2':
- error (_("trace API error 0x%s."), ++buf);
- default:
- error (_("Target returns error code '%s'."), buf);
- }
-}
-
-/* Utility: wait for reply from stub, while accepting "O" packets. */
-static char *
-remote_get_noisy_reply (char **buf_p,
- long *sizeof_buf)
-{
- do /* Loop on reply from remote stub. */
- {
- char *buf;
- QUIT; /* allow user to bail out with ^C */
- getpkt (buf_p, sizeof_buf, 0);
- buf = *buf_p;
- if (buf[0] == 0)
- error (_("Target does not support this command."));
- else if (buf[0] == 'E')
- trace_error (buf);
- else if (buf[0] == 'O' &&
- buf[1] != 'K')
- remote_console_output (buf + 1); /* 'O' message from stub */
- else
- return buf; /* here's the actual reply */
- }
- while (1);
-}
-
/* Set traceframe number to NUM. */
static void
set_traceframe_num (int num)
@@ -449,37 +384,17 @@ tvariables_info (char *args, int from_tty)
char *reply;
ULONGEST tval;
- if (target_is_remote ())
- {
- char buf[20];
-
- for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
- {
- /* We don't know anything about the value until we get a
- valid packet. */
- tsv->value_known = 0;
- sprintf (buf, "qTV:%x", tsv->number);
- putpkt (buf);
- reply = remote_get_noisy_reply (&target_buf, &target_buf_size);
- if (reply && *reply)
- {
- if (*reply == 'V')
- {
- unpack_varlen_hex (reply + 1, &tval);
- tsv->value = (LONGEST) tval;
- tsv->value_known = 1;
- }
- /* FIXME say anything about oddball replies? */
- }
- }
- }
-
if (VEC_length (tsv_s, tvariables) == 0)
{
printf_filtered (_("No trace state variables.\n"));
return;
}
+ /* Try to acquire values from the target. */
+ for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
+ tsv->value_known = target_get_trace_state_variable_value (tsv->number,
+ &(tsv->value));
+
printf_filtered (_("Name\t\t Initial\tCurrent\n"));
for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
@@ -1293,28 +1208,8 @@ stringify_collection_list (struct collection_list *list, char *string)
return *str_list;
}
-static void
-free_actions_list_cleanup_wrapper (void *al)
-{
- free_actions_list (al);
-}
-
-static void
-free_actions_list (char **actions_list)
-{
- int ndx;
-
- if (actions_list == 0)
- return;
-
- for (ndx = 0; actions_list[ndx]; ndx++)
- xfree (actions_list[ndx]);
-
- xfree (actions_list);
-}
-
/* Render all actions into gdb protocol. */
-static void
+/*static*/ void
encode_actions (struct breakpoint *t, char ***tdp_actions,
char ***stepping_actions)
{
@@ -1583,49 +1478,6 @@ add_aexpr (struct collection_list *collect, struct agent_expr *aexpr)
collect->next_aexpr_elt++;
}
-/* Set "transparent" memory ranges
-
- Allow trace mechanism to treat text-like sections
- (and perhaps all read-only sections) transparently,
- i.e. don't reject memory requests from these address ranges
- just because they haven't been collected. */
-
-static void
-remote_set_transparent_ranges (void)
-{
- asection *s;
- bfd_size_type size;
- bfd_vma lma;
- int anysecs = 0;
-
- if (!exec_bfd)
- return; /* No information to give. */
-
- strcpy (target_buf, "QTro");
- for (s = exec_bfd->sections; s; s = s->next)
- {
- char tmp1[40], tmp2[40];
-
- if ((s->flags & SEC_LOAD) == 0 ||
- /* (s->flags & SEC_CODE) == 0 || */
- (s->flags & SEC_READONLY) == 0)
- continue;
-
- anysecs = 1;
- lma = s->lma;
- size = bfd_get_section_size (s);
- sprintf_vma (tmp1, lma);
- sprintf_vma (tmp2, lma + size);
- sprintf (target_buf + strlen (target_buf),
- ":%s,%s", tmp1, tmp2);
- }
- if (anysecs)
- {
- putpkt (target_buf);
- getpkt (&target_buf, &target_buf_size, 0);
- }
-}
-
/* tstart command:
Tell target to clear any previous trace experiment.
@@ -1633,8 +1485,6 @@ remote_set_transparent_ranges (void)
to the target. If no errors,
Tell target to start a new trace experiment. */
-int download_tracepoint (struct breakpoint *t);
-
static void
trace_start_command (char *args, int from_tty)
{
@@ -1647,249 +1497,93 @@ trace_start_command (char *args, int from_tty)
dont_repeat (); /* Like "run", dangerous to repeat accidentally. */
- if (target_is_remote ())
- {
- putpkt ("QTinit");
- remote_get_noisy_reply (&target_buf, &target_buf_size);
- if (strcmp (target_buf, "OK"))
- error (_("Target does not support this command."));
-
- tp_vec = all_tracepoints ();
- for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
- {
- 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)
- {
- if (tsv->initial_value != 0)
- {
- sprintf (buf, "QTDV:%x:%s",
- tsv->number, phex ((ULONGEST) tsv->initial_value, 8));
- putpkt (buf);
- remote_get_noisy_reply (&target_buf, &target_buf_size);
- }
- }
-
- /* Tell target to treat text-like sections as transparent. */
- remote_set_transparent_ranges ();
- /* Now insert traps and begin collecting data. */
- putpkt ("QTStart");
- remote_get_noisy_reply (&target_buf, &target_buf_size);
- if (strcmp (target_buf, "OK"))
- error (_("Bogus reply from target: %s"), target_buf);
- set_traceframe_num (-1); /* All old traceframes invalidated. */
- set_tracepoint_num (-1);
- set_traceframe_context (NULL);
- trace_running_p = 1;
- if (deprecated_trace_start_stop_hook)
- deprecated_trace_start_stop_hook (1, from_tty);
-
- }
- else
- error (_("Trace can only be run on remote targets."));
-}
-
-/* Send the definition of a single tracepoint to the target. Return 1
- if successful, 0 if not. */
-
-int
-download_tracepoint (struct breakpoint *t)
-{
- CORE_ADDR tpaddr;
- char tmp[40];
- char buf[2048];
- char **tdp_actions;
- char **stepping_actions;
- int ndx;
- struct cleanup *old_chain = NULL;
- struct agent_expr *aexpr;
- struct cleanup *aexpr_chain = NULL;
-
- tpaddr = t->loc->address;
- sprintf_vma (tmp, (t->loc ? tpaddr : 0));
- sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number,
- tmp, /* address */
- (t->enable_state == bp_enabled ? 'E' : 'D'),
- t->step_count, t->pass_count);
- /* Fast tracepoints are mostly handled by the target, but we can
- tell the target how big of an instruction block should be moved
- around. */
- if (t->type == bp_fast_tracepoint)
+ target_trace_init ();
+
+ tp_vec = all_tracepoints ();
+ for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
{
- /* Only test for support at download time; we may not know
- target capabilities at definition time. */
- if (remote_supports_fast_tracepoints ())
- {
- int isize;
-
- if (gdbarch_fast_tracepoint_valid_at (get_current_arch (),
- tpaddr, &isize, NULL))
- sprintf (buf + strlen (buf), ":F%x", isize);
- else
- /* If it passed validation at definition but fails now,
- something is very wrong. */
- internal_error (__FILE__, __LINE__,
- "Fast tracepoint not valid during download");
- }
- else
- /* Fast tracepoints are functionally identical to regular
- tracepoints, so don't take lack of support as a reason to
- give up on the trace run. */
- warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
+ t->number_on_target = 0;
+ target_download_tracepoint (t);
+ t->number_on_target = t->number;
+ any_downloaded = 1;
}
- /* If the tracepoint has a conditional, make it into an agent
- expression and append to the definition. */
- if (t->loc->cond)
+ 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)
{
- /* Only test support at download time, we may not know target
- capabilities at definition time. */
- if (remote_supports_cond_tracepoints ())
- {
- aexpr = gen_eval_for_expr (t->loc->address, t->loc->cond);
- aexpr_chain = make_cleanup_free_agent_expr (aexpr);
- sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
- mem2hex (aexpr->buf, buf + strlen (buf), aexpr->len);
- do_cleanups (aexpr_chain);
- }
- else
- warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
+ if (tsv->initial_value != 0)
+ target_download_trace_state_variable (tsv);
}
+
+ /* Tell target to treat text-like sections as transparent. */
+ target_trace_set_readonly_regions ();
- if (t->actions || *default_collect)
- strcat (buf, "-");
- putpkt (buf);
- remote_get_noisy_reply (&target_buf, &target_buf_size);
- if (strcmp (target_buf, "OK"))
- error (_("Target does not support tracepoints."));
-
- if (!t->actions && !*default_collect)
- return 1;
-
- encode_actions (t, &tdp_actions, &stepping_actions);
- old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
- tdp_actions);
- (void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions);
+ /* Now insert traps and begin collecting data. */
+ target_trace_start ();
- /* do_single_steps (t); */
- if (tdp_actions)
- {
- for (ndx = 0; tdp_actions[ndx]; ndx++)
- {
- QUIT; /* allow user to bail out with ^C */
- sprintf (buf, "QTDP:-%x:%s:%s%c",
- t->number, tmp, /* address */
- tdp_actions[ndx],
- ((tdp_actions[ndx + 1] || stepping_actions)
- ? '-' : 0));
- putpkt (buf);
- remote_get_noisy_reply (&target_buf,
- &target_buf_size);
- if (strcmp (target_buf, "OK"))
- error (_("Error on target while setting tracepoints."));
- }
- }
- if (stepping_actions)
- {
- for (ndx = 0; stepping_actions[ndx]; ndx++)
- {
- QUIT; /* allow user to bail out with ^C */
- sprintf (buf, "QTDP:-%x:%s:%s%s%s",
- t->number, tmp, /* address */
- ((ndx == 0) ? "S" : ""),
- stepping_actions[ndx],
- (stepping_actions[ndx + 1] ? "-" : ""));
- putpkt (buf);
- remote_get_noisy_reply (&target_buf,
- &target_buf_size);
- if (strcmp (target_buf, "OK"))
- error (_("Error on target while setting tracepoints."));
- }
- }
- do_cleanups (old_chain);
- return 1;
+ /* Reset our local state. */
+ set_traceframe_num (-1);
+ set_tracepoint_num (-1);
+ set_traceframe_context (NULL);
+ trace_running_p = 1;
}
/* tstop command */
static void
trace_stop_command (char *args, int from_tty)
{
- if (target_is_remote ())
- {
- stop_tracing ();
- if (deprecated_trace_start_stop_hook)
- deprecated_trace_start_stop_hook (0, from_tty);
- }
- else
- error (_("Trace can only be run on remote targets."));
+ stop_tracing ();
}
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);
+ target_trace_stop ();
trace_running_p = 0;
}
unsigned long trace_running_p;
-void
+int
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);
+ int status = target_get_trace_status (NULL);
/* exported for use by the GUI */
- trace_running_p = (target_buf[1] == '1');
+ trace_running_p = (status > 0);
+
+ return status;
}
/* tstatus command */
static void
trace_status_command (char *args, int from_tty)
{
- if (target_is_remote ())
+ int status = get_trace_status ();
+
+ if (status < 0)
+ printf_filtered (_("Trace can not be run on the target.\n"));
+ else if (trace_running_p)
{
- get_trace_status ();
-
- if (trace_running_p)
- {
- 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"));
- }
+ 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 is not running on the target.\n"));
-
- 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"));
-
+ printf_filtered (_("Trace will stop if GDB disconnects.\n"));
}
else
- error (_("Trace can only be run on remote targets."));
+ printf_filtered (_("Trace is not running on the target.\n"));
+
+ 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"));
}
void
@@ -1912,8 +1606,8 @@ disconnect_or_stop_tracing (int from_tty)
/* Worker function for the various flavors of the tfind command. */
static void
-finish_tfind_command (char **msg,
- long *sizeof_msg,
+finish_tfind_command (enum trace_find_type type, int num,
+ ULONGEST addr1, ULONGEST addr2,
int from_tty)
{
int target_frameno = -1, target_tracept = -1;
@@ -1923,64 +1617,52 @@ finish_tfind_command (char **msg,
old_frame_id = get_frame_id (get_current_frame ());
- putpkt (*msg);
- reply = remote_get_noisy_reply (msg, sizeof_msg);
-
- while (reply && *reply)
- switch (*reply)
- {
- case 'F':
- if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
- {
- /* A request for a non-existant trace frame has failed.
- Our response will be different, depending on FROM_TTY:
-
- If FROM_TTY is true, meaning that this command was
- typed interactively by the user, then give an error
- and DO NOT change the state of traceframe_number etc.
-
- However if FROM_TTY is false, meaning that we're either
- in a script, a loop, or a user-defined command, then
- DON'T give an error, but DO change the state of
- traceframe_number etc. to invalid.
-
- The rationalle is that if you typed the command, you
- might just have committed a typo or something, and you'd
- like to NOT lose your current debugging state. However
- if you're in a user-defined command or especially in a
- loop, then you need a way to detect that the command
- failed WITHOUT aborting. This allows you to write
- scripts that search thru the trace buffer until the end,
- and then continue on to do something else. */
-
- if (from_tty)
- error (_("Target failed to find requested trace frame."));
- else
- {
- if (info_verbose)
- printf_filtered ("End of trace buffer.\n");
- /* The following will not recurse, since it's
- special-cased. */
- trace_find_command ("-1", from_tty);
- reply = NULL; /* Break out of loop
- (avoid recursive nonsense). */
- }
- }
- break;
- case 'T':
- if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
- error (_("Target failed to find requested trace frame."));
- break;
- case 'O': /* "OK"? */
- if (reply[1] == 'K' && reply[2] == '\0')
- reply += 2;
- else
- error (_("Bogus reply from target: %s"), reply);
- break;
- default:
- error (_("Bogus reply from target: %s"), reply);
- }
-
+ target_frameno = target_trace_find (type, num, addr1, addr2,
+ &target_tracept);
+
+ if (type == tfind_number
+ && num == -1
+ && target_frameno == -1)
+ {
+ /* We told the target to get out of tfind mode, and it did. */
+ }
+ else if (target_frameno == -1)
+ {
+ /* A request for a non-existant trace frame has failed.
+ Our response will be different, depending on FROM_TTY:
+
+ If FROM_TTY is true, meaning that this command was
+ typed interactively by the user, then give an error
+ and DO NOT change the state of traceframe_number etc.
+
+ However if FROM_TTY is false, meaning that we're either
+ in a script, a loop, or a user-defined command, then
+ DON'T give an error, but DO change the state of
+ traceframe_number etc. to invalid.
+
+ The rationalle is that if you typed the command, you
+ might just have committed a typo or something, and you'd
+ like to NOT lose your current debugging state. However
+ if you're in a user-defined command or especially in a
+ loop, then you need a way to detect that the command
+ failed WITHOUT aborting. This allows you to write
+ scripts that search thru the trace buffer until the end,
+ and then continue on to do something else. */
+
+ if (from_tty)
+ error (_("Target failed to find requested trace frame."));
+ else
+ {
+ if (info_verbose)
+ printf_filtered ("End of trace buffer.\n");
+#if 0 /* dubious now? */
+ /* The following will not recurse, since it's
+ special-cased. */
+ trace_find_command ("-1", from_tty);
+#endif
+ }
+ }
+
tp = get_tracepoint_by_number_on_target (target_tracept);
reinit_frame_cache ();
@@ -2033,41 +1715,35 @@ trace_find_command (char *args, int from_tty)
{ /* this should only be called with a numeric argument */
int frameno = -1;
- if (target_is_remote ())
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
+
+ if (args == 0 || *args == 0)
+ { /* TFIND with no args means find NEXT trace frame. */
+ if (traceframe_number == -1)
+ frameno = 0; /* "next" is first one */
+ else
+ frameno = traceframe_number + 1;
+ }
+ else if (0 == strcmp (args, "-"))
{
- if (trace_running_p)
- error ("May not look at trace frames while trace is running.");
-
- if (deprecated_trace_find_hook)
- deprecated_trace_find_hook (args, from_tty);
-
- if (args == 0 || *args == 0)
- { /* TFIND with no args means find NEXT trace frame. */
- if (traceframe_number == -1)
- frameno = 0; /* "next" is first one */
- else
- frameno = traceframe_number + 1;
- }
- else if (0 == strcmp (args, "-"))
- {
- if (traceframe_number == -1)
- error (_("not debugging trace buffer"));
- else if (from_tty && traceframe_number == 0)
- error (_("already at start of trace buffer"));
-
- frameno = traceframe_number - 1;
- }
- else
- frameno = parse_and_eval_long (args);
+ if (traceframe_number == -1)
+ error (_("not debugging trace buffer"));
+ else if (from_tty && traceframe_number == 0)
+ error (_("already at start of trace buffer"));
+
+ frameno = traceframe_number - 1;
+ }
+ /* A hack to work around eval's need for fp to have been collected. */
+ else if (0 == strcmp (args, "-1"))
+ frameno = -1;
+ else
+ frameno = parse_and_eval_long (args);
- if (frameno < -1)
- error (_("invalid input (%d is less than zero)"), frameno);
+ if (frameno < -1)
+ error (_("invalid input (%d is less than zero)"), frameno);
- sprintf (target_buf, "QTFrame:%x", frameno);
- finish_tfind_command (&target_buf, &target_buf_size, from_tty);
- }
- else
- error (_("Trace can only be run on remote targets."));
+ finish_tfind_command (tfind_number, frameno, 0, 0, from_tty);
}
/* tfind end */
@@ -2098,22 +1774,15 @@ trace_find_pc_command (char *args, int from_tty)
CORE_ADDR pc;
char tmp[40];
- if (target_is_remote ())
- {
- if (trace_running_p)
- error ("May not look at trace frames while trace is running.");
-
- if (args == 0 || *args == 0)
- pc = regcache_read_pc (get_current_regcache ());
- else
- pc = parse_and_eval_address (args);
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
- sprintf_vma (tmp, pc);
- sprintf (target_buf, "QTFrame:pc:%s", tmp);
- finish_tfind_command (&target_buf, &target_buf_size, from_tty);
- }
+ if (args == 0 || *args == 0)
+ pc = regcache_read_pc (get_current_regcache ());
else
- error (_("Trace can only be run on remote targets."));
+ pc = parse_and_eval_address (args);
+
+ finish_tfind_command (tfind_pc, 0, pc, 0, from_tty);
}
/* tfind tracepoint command */
@@ -2123,33 +1792,27 @@ trace_find_tracepoint_command (char *args, int from_tty)
int tdp;
struct breakpoint *tp;
- if (target_is_remote ())
- {
- if (trace_running_p)
- error ("May not look at trace frames while trace is running.");
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
- if (args == 0 || *args == 0)
- {
- if (tracepoint_number == -1)
- error (_("No current tracepoint -- please supply an argument."));
- else
- tdp = tracepoint_number; /* default is current TDP */
- }
+ if (args == 0 || *args == 0)
+ {
+ if (tracepoint_number == -1)
+ error (_("No current tracepoint -- please supply an argument."));
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);
+ tdp = tracepoint_number; /* default is current TDP */
}
else
- error (_("Trace can only be run on remote targets."));
+ 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;
+
+ finish_tfind_command (tfind_tp, tdp, 0, 0, from_tty);
}
/* TFIND LINE command:
@@ -2169,94 +1832,78 @@ trace_find_line_command (char *args, int from_tty)
struct cleanup *old_chain;
char startpc_str[40], endpc_str[40];
- if (target_is_remote ())
- {
- if (trace_running_p)
- error ("May not look at trace frames while trace is running.");
-
- if (args == 0 || *args == 0)
- {
- sal = find_pc_line (get_frame_pc (get_current_frame ()), 0);
- sals.nelts = 1;
- sals.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- sals.sals[0] = sal;
- }
- else
- {
- sals = decode_line_spec (args, 1);
- sal = sals.sals[0];
- }
-
- old_chain = make_cleanup (xfree, sals.sals);
- if (sal.symtab == 0)
- {
- struct gdbarch *gdbarch = get_current_arch ();
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
- printf_filtered ("TFIND: No line number information available");
- if (sal.pc != 0)
- {
- /* This is useful for "info line *0x7f34". If we can't
- tell the user about a source line, at least let them
- have the symbolic address. */
- printf_filtered (" for address ");
- wrap_here (" ");
- print_address (gdbarch, sal.pc, gdb_stdout);
- printf_filtered (";\n -- will attempt to find by PC. \n");
- }
- else
- {
- printf_filtered (".\n");
- return; /* No line, no PC; what can we do? */
- }
- }
- else if (sal.line > 0
- && find_line_pc_range (sal, &start_pc, &end_pc))
+ if (args == 0 || *args == 0)
+ {
+ sal = find_pc_line (get_frame_pc (get_current_frame ()), 0);
+ sals.nelts = 1;
+ sals.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ sals.sals[0] = sal;
+ }
+ else
+ {
+ sals = decode_line_spec (args, 1);
+ sal = sals.sals[0];
+ }
+
+ old_chain = make_cleanup (xfree, sals.sals);
+ if (sal.symtab == 0)
+ {
+ printf_filtered ("TFIND: No line number information available");
+ if (sal.pc != 0)
{
- struct gdbarch *gdbarch = get_objfile_arch (sal.symtab->objfile);
-
- if (start_pc == end_pc)
- {
- printf_filtered ("Line %d of \"%s\"",
- sal.line, sal.symtab->filename);
- wrap_here (" ");
- printf_filtered (" is at address ");
- print_address (gdbarch, start_pc, gdb_stdout);
- wrap_here (" ");
- printf_filtered (" but contains no code.\n");
- sal = find_pc_line (start_pc, 0);
- if (sal.line > 0 &&
- find_line_pc_range (sal, &start_pc, &end_pc) &&
- start_pc != end_pc)
- printf_filtered ("Attempting to find line %d instead.\n",
- sal.line);
- else
- error (_("Cannot find a good line."));
- }
- }
- else
- /* Is there any case in which we get here, and have an address
- which the user would want to see? If we have debugging
- symbols and no line numbers? */
- error (_("Line number %d is out of range for \"%s\"."),
- sal.line, sal.symtab->filename);
-
- sprintf_vma (startpc_str, start_pc);
- sprintf_vma (endpc_str, end_pc - 1);
- /* Find within range of stated line. */
- if (args && *args)
- sprintf (target_buf, "QTFrame:range:%s:%s",
- startpc_str, endpc_str);
- /* Find OUTSIDE OF range of CURRENT line. */
- else
- sprintf (target_buf, "QTFrame:outside:%s:%s",
- startpc_str, endpc_str);
- finish_tfind_command (&target_buf, &target_buf_size,
- from_tty);
- do_cleanups (old_chain);
+ /* This is useful for "info line *0x7f34". If we can't
+ tell the user about a source line, at least let them
+ have the symbolic address. */
+ printf_filtered (" for address ");
+ wrap_here (" ");
+ print_address (get_current_arch (), sal.pc, gdb_stdout);
+ printf_filtered (";\n -- will attempt to find by PC. \n");
+ }
+ else
+ {
+ printf_filtered (".\n");
+ return; /* No line, no PC; what can we do? */
+ }
}
+ else if (sal.line > 0
+ && find_line_pc_range (sal, &start_pc, &end_pc))
+ {
+ if (start_pc == end_pc)
+ {
+ printf_filtered ("Line %d of \"%s\"",
+ sal.line, sal.symtab->filename);
+ wrap_here (" ");
+ printf_filtered (" is at address ");
+ print_address (get_current_arch (), start_pc, gdb_stdout);
+ wrap_here (" ");
+ printf_filtered (" but contains no code.\n");
+ sal = find_pc_line (start_pc, 0);
+ if (sal.line > 0
+ && find_line_pc_range (sal, &start_pc, &end_pc)
+ && start_pc != end_pc)
+ printf_filtered ("Attempting to find line %d instead.\n",
+ sal.line);
+ else
+ error (_("Cannot find a good line."));
+ }
+ }
+ else
+ /* Is there any case in which we get here, and have an address
+ which the user would want to see? If we have debugging
+ symbols and no line numbers? */
+ error (_("Line number %d is out of range for \"%s\"."),
+ sal.line, sal.symtab->filename);
+
+ /* Find within range of stated line. */
+ if (args && *args)
+ finish_tfind_command (tfind_range, 0, start_pc, end_pc - 1, from_tty);
else
- error (_("Trace can only be run on remote targets."));
+ finish_tfind_command (tfind_outside, 0, start_pc, end_pc - 1, from_tty);
+ do_cleanups (old_chain);
}
/* tfind range command */
@@ -2267,38 +1914,30 @@ trace_find_range_command (char *args, int from_tty)
char start_str[40], stop_str[40];
char *tmp;
- if (target_is_remote ())
- {
- if (trace_running_p)
- error ("May not look at trace frames while trace is running.");
-
- if (args == 0 || *args == 0)
- { /* XXX FIXME: what should default behavior be? */
- printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
- return;
- }
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
- if (0 != (tmp = strchr (args, ',')))
- {
- *tmp++ = '\0'; /* terminate start address */
- while (isspace ((int) *tmp))
- tmp++;
- start = parse_and_eval_address (args);
- stop = parse_and_eval_address (tmp);
- }
- else
- { /* no explicit end address? */
- start = parse_and_eval_address (args);
- stop = start + 1; /* ??? */
- }
+ if (args == 0 || *args == 0)
+ { /* XXX FIXME: what should default behavior be? */
+ printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
+ return;
+ }
- sprintf_vma (start_str, start);
- sprintf_vma (stop_str, stop);
- sprintf (target_buf, "QTFrame:range:%s:%s", start_str, stop_str);
- finish_tfind_command (&target_buf, &target_buf_size, from_tty);
+ if (0 != (tmp = strchr (args, ',')))
+ {
+ *tmp++ = '\0'; /* terminate start address */
+ while (isspace ((int) *tmp))
+ tmp++;
+ start = parse_and_eval_address (args);
+ stop = parse_and_eval_address (tmp);
}
else
- error (_("Trace can only be run on remote targets."));
+ { /* no explicit end address? */
+ start = parse_and_eval_address (args);
+ stop = start + 1; /* ??? */
+ }
+
+ finish_tfind_command (tfind_range, 0, start, stop, from_tty);
}
/* tfind outside command */
@@ -2309,38 +1948,30 @@ trace_find_outside_command (char *args, int from_tty)
char start_str[40], stop_str[40];
char *tmp;
- if (target_is_remote ())
- {
- if (trace_running_p)
- error ("May not look at trace frames while trace is running.");
-
- if (args == 0 || *args == 0)
- { /* XXX FIXME: what should default behavior be? */
- printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
- return;
- }
+ if (trace_running_p)
+ error ("May not look at trace frames while trace is running.");
- if (0 != (tmp = strchr (args, ',')))
- {
- *tmp++ = '\0'; /* terminate start address */
- while (isspace ((int) *tmp))
- tmp++;
- start = parse_and_eval_address (args);
- stop = parse_and_eval_address (tmp);
- }
- else
- { /* no explicit end address? */
- start = parse_and_eval_address (args);
- stop = start + 1; /* ??? */
- }
+ if (args == 0 || *args == 0)
+ { /* XXX FIXME: what should default behavior be? */
+ printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
+ return;
+ }
- sprintf_vma (start_str, start);
- sprintf_vma (stop_str, stop);
- sprintf (target_buf, "QTFrame:outside:%s:%s", start_str, stop_str);
- finish_tfind_command (&target_buf, &target_buf_size, from_tty);
+ if (0 != (tmp = strchr (args, ',')))
+ {
+ *tmp++ = '\0'; /* terminate start address */
+ while (isspace ((int) *tmp))
+ tmp++;
+ start = parse_and_eval_address (args);
+ stop = parse_and_eval_address (tmp);
}
else
- error (_("Trace can only be run on remote targets."));
+ { /* no explicit end address? */
+ start = parse_and_eval_address (args);
+ stop = start + 1; /* ??? */
+ }
+
+ finish_tfind_command (tfind_outside, 0, start, stop, from_tty);
}
/* info scope command: list the locals for a scope. */
@@ -2511,12 +2142,6 @@ trace_dump_command (char *args, int from_tty)
int stepping_actions = 0;
int stepping_frame = 0;
- if (!target_is_remote ())
- {
- error (_("Trace can only be run on remote targets."));
- return;
- }
-
if (tracepoint_number == -1)
{
warning (_("No current trace frame."));
@@ -2620,17 +2245,7 @@ trace_dump_command (char *args, int from_tty)
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."));
+ target_set_disconnected_tracing (value);
}
static void
@@ -2847,7 +2462,4 @@ trace data collected in the meantime."),
NULL,
&setlist,
&showlist);
-
- target_buf_size = 2048;
- target_buf = xmalloc (target_buf_size);
}
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
index 0ac2da6..5d2862a 100644
--- a/gdb/tracepoint.h
+++ b/gdb/tracepoint.h
@@ -65,6 +65,8 @@ struct trace_state_variable
extern unsigned long trace_running_p;
+extern char *default_collect;
+
/* A hook used to notify the UI of tracepoint operations. */
extern void (*deprecated_trace_find_hook) (char *arg, int from_tty);