From 35b1e5cca081f63a45e2d6bbc90010e553f7c5c8 Mon Sep 17 00:00:00 2001 From: Stan Shebs Date: Thu, 7 Jan 2010 19:17:46 +0000 Subject: [PATCH] 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. --- gdb/ChangeLog | 57 +++ gdb/remote.c | 396 +++++++++++++++++++- gdb/target.c | 40 ++ gdb/target.h | 86 +++++ gdb/tracepoint.c | 922 ++++++++++++++--------------------------------- gdb/tracepoint.h | 2 + 6 files changed, 847 insertions(+), 656 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6d3938d013..3430364149 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,62 @@ 2010-01-07 Stan Shebs + 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 diff --git a/gdb/remote.c b/gdb/remote.c index 262b97ffcd..9c50f7ef92 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; @@ -8942,6 +8999,331 @@ remote_supports_fast_tracepoints (void) return rs->fast_tracepoints; } +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) { @@ -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 38cd508e90..25a2cd736d 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 9a89b93175..20cbe29eb9 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 5d19934d2e..0dfe23cdf8 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 ()) + target_trace_init (); + + tp_vec = all_tracepoints (); + for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++) { - 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); - + t->number_on_target = 0; + target_download_tracepoint (t); + t->number_on_target = t->number; + any_downloaded = 1; } - 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) + 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 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); - } - /* 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); - 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.")); + /* Now insert traps and begin collecting data. */ + target_trace_start (); - 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); - - /* 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); + 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: - 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. - 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); - } + 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 (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 (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); + 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 (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 - error (_("Trace can only be run on remote targets.")); + frameno = parse_and_eval_long (args); + + if (frameno < -1) + error (_("invalid input (%d is less than zero)"), frameno); + + 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 (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); - - 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 (args == 0 || *args == 0) { - 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 (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) { - 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 (); - - 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)) - { - 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); + 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 - error (_("Trace can only be run on remote targets.")); + { + 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) + { + /* 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 + 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 ,\n"); + return; + } + + if (0 != (tmp = strchr (args, ','))) { - 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 ,\n"); - return; - } - - 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; /* ??? */ - } - - 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); + *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 ,\n"); + return; + } + + if (0 != (tmp = strchr (args, ','))) { - 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 ,\n"); - return; - } - - 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; /* ??? */ - } - - 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); + *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 0ac2da6abd..5d2862a7b6 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);