xref: /dflybsd-src/contrib/gdb-7/gdb/tracepoint.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* Tracing functionality for remote targets in custom GDB protocol
25796c8dcSSimon Schubert 
3*ef5ccd6cSJohn Marino    Copyright (C) 1997-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    This file is part of GDB.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert    (at your option) any later version.
115796c8dcSSimon Schubert 
125796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155796c8dcSSimon Schubert    GNU General Public License for more details.
165796c8dcSSimon Schubert 
175796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
195796c8dcSSimon Schubert 
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "arch-utils.h"
225796c8dcSSimon Schubert #include "symtab.h"
235796c8dcSSimon Schubert #include "frame.h"
245796c8dcSSimon Schubert #include "gdbtypes.h"
255796c8dcSSimon Schubert #include "expression.h"
265796c8dcSSimon Schubert #include "gdbcmd.h"
275796c8dcSSimon Schubert #include "value.h"
285796c8dcSSimon Schubert #include "target.h"
295796c8dcSSimon Schubert #include "language.h"
305796c8dcSSimon Schubert #include "gdb_string.h"
315796c8dcSSimon Schubert #include "inferior.h"
325796c8dcSSimon Schubert #include "breakpoint.h"
335796c8dcSSimon Schubert #include "tracepoint.h"
345796c8dcSSimon Schubert #include "linespec.h"
355796c8dcSSimon Schubert #include "regcache.h"
365796c8dcSSimon Schubert #include "completer.h"
375796c8dcSSimon Schubert #include "block.h"
385796c8dcSSimon Schubert #include "dictionary.h"
395796c8dcSSimon Schubert #include "observer.h"
405796c8dcSSimon Schubert #include "user-regs.h"
415796c8dcSSimon Schubert #include "valprint.h"
425796c8dcSSimon Schubert #include "gdbcore.h"
435796c8dcSSimon Schubert #include "objfiles.h"
44cf7f2e2dSJohn Marino #include "filenames.h"
45cf7f2e2dSJohn Marino #include "gdbthread.h"
46cf7f2e2dSJohn Marino #include "stack.h"
47cf7f2e2dSJohn Marino #include "gdbcore.h"
48cf7f2e2dSJohn Marino #include "remote.h"
49cf7f2e2dSJohn Marino #include "source.h"
505796c8dcSSimon Schubert #include "ax.h"
515796c8dcSSimon Schubert #include "ax-gdb.h"
52c50c785cSJohn Marino #include "memrange.h"
53c50c785cSJohn Marino #include "exceptions.h"
54a45ae5f8SJohn Marino #include "cli/cli-utils.h"
55*ef5ccd6cSJohn Marino #include "probe.h"
565796c8dcSSimon Schubert 
575796c8dcSSimon Schubert /* readline include files */
585796c8dcSSimon Schubert #include "readline/readline.h"
595796c8dcSSimon Schubert #include "readline/history.h"
605796c8dcSSimon Schubert 
615796c8dcSSimon Schubert /* readline defines this.  */
625796c8dcSSimon Schubert #undef savestring
635796c8dcSSimon Schubert 
645796c8dcSSimon Schubert #ifdef HAVE_UNISTD_H
655796c8dcSSimon Schubert #include <unistd.h>
665796c8dcSSimon Schubert #endif
675796c8dcSSimon Schubert 
68cf7f2e2dSJohn Marino #ifndef O_LARGEFILE
69cf7f2e2dSJohn Marino #define O_LARGEFILE 0
70cf7f2e2dSJohn Marino #endif
71cf7f2e2dSJohn Marino 
725796c8dcSSimon Schubert /* Maximum length of an agent aexpression.
735796c8dcSSimon Schubert    This accounts for the fact that packets are limited to 400 bytes
745796c8dcSSimon Schubert    (which includes everything -- including the checksum), and assumes
755796c8dcSSimon Schubert    the worst case of maximum length for each of the pieces of a
765796c8dcSSimon Schubert    continuation packet.
775796c8dcSSimon Schubert 
785796c8dcSSimon Schubert    NOTE: expressions get mem2hex'ed otherwise this would be twice as
795796c8dcSSimon Schubert    large.  (400 - 31)/2 == 184 */
805796c8dcSSimon Schubert #define MAX_AGENT_EXPR_LEN	184
815796c8dcSSimon Schubert 
82c50c785cSJohn Marino #define TFILE_PID (1)
83c50c785cSJohn Marino 
84cf7f2e2dSJohn Marino /* A hook used to notify the UI of tracepoint operations.  */
85cf7f2e2dSJohn Marino 
86cf7f2e2dSJohn Marino void (*deprecated_trace_find_hook) (char *arg, int from_tty);
87cf7f2e2dSJohn Marino void (*deprecated_trace_start_stop_hook) (int start, int from_tty);
885796c8dcSSimon Schubert 
895796c8dcSSimon Schubert extern void (*deprecated_readline_begin_hook) (char *, ...);
905796c8dcSSimon Schubert extern char *(*deprecated_readline_hook) (char *);
915796c8dcSSimon Schubert extern void (*deprecated_readline_end_hook) (void);
925796c8dcSSimon Schubert 
935796c8dcSSimon Schubert /*
945796c8dcSSimon Schubert    Tracepoint.c:
955796c8dcSSimon Schubert 
965796c8dcSSimon Schubert    This module defines the following debugger commands:
975796c8dcSSimon Schubert    trace            : set a tracepoint on a function, line, or address.
985796c8dcSSimon Schubert    info trace       : list all debugger-defined tracepoints.
995796c8dcSSimon Schubert    delete trace     : delete one or more tracepoints.
1005796c8dcSSimon Schubert    enable trace     : enable one or more tracepoints.
1015796c8dcSSimon Schubert    disable trace    : disable one or more tracepoints.
1025796c8dcSSimon Schubert    actions          : specify actions to be taken at a tracepoint.
1035796c8dcSSimon Schubert    passcount        : specify a pass count for a tracepoint.
1045796c8dcSSimon Schubert    tstart           : start a trace experiment.
1055796c8dcSSimon Schubert    tstop            : stop a trace experiment.
1065796c8dcSSimon Schubert    tstatus          : query the status of a trace experiment.
1075796c8dcSSimon Schubert    tfind            : find a trace frame in the trace buffer.
1085796c8dcSSimon Schubert    tdump            : print everything collected at the current tracepoint.
1095796c8dcSSimon Schubert    save-tracepoints : write tracepoint setup into a file.
1105796c8dcSSimon Schubert 
1115796c8dcSSimon Schubert    This module defines the following user-visible debugger variables:
1125796c8dcSSimon Schubert    $trace_frame : sequence number of trace frame currently being debugged.
1135796c8dcSSimon Schubert    $trace_line  : source line of trace frame currently being debugged.
1145796c8dcSSimon Schubert    $trace_file  : source file of trace frame currently being debugged.
1155796c8dcSSimon Schubert    $tracepoint  : tracepoint number of trace frame currently being debugged.
1165796c8dcSSimon Schubert  */
1175796c8dcSSimon Schubert 
1185796c8dcSSimon Schubert 
1195796c8dcSSimon Schubert /* ======= Important global variables: ======= */
1205796c8dcSSimon Schubert 
121cf7f2e2dSJohn Marino /* The list of all trace state variables.  We don't retain pointers to
122cf7f2e2dSJohn Marino    any of these for any reason - API is by name or number only - so it
123cf7f2e2dSJohn Marino    works to have a vector of objects.  */
124cf7f2e2dSJohn Marino 
125cf7f2e2dSJohn Marino typedef struct trace_state_variable tsv_s;
126cf7f2e2dSJohn Marino DEF_VEC_O(tsv_s);
127cf7f2e2dSJohn Marino 
128c50c785cSJohn Marino /* An object describing the contents of a traceframe.  */
129c50c785cSJohn Marino 
130c50c785cSJohn Marino struct traceframe_info
131c50c785cSJohn Marino {
132c50c785cSJohn Marino   /* Collected memory.  */
133c50c785cSJohn Marino   VEC(mem_range_s) *memory;
134c50c785cSJohn Marino };
135c50c785cSJohn Marino 
136cf7f2e2dSJohn Marino static VEC(tsv_s) *tvariables;
137cf7f2e2dSJohn Marino 
138cf7f2e2dSJohn Marino /* The next integer to assign to a variable.  */
139cf7f2e2dSJohn Marino 
140cf7f2e2dSJohn Marino static int next_tsv_number = 1;
141cf7f2e2dSJohn Marino 
1425796c8dcSSimon Schubert /* Number of last traceframe collected.  */
1435796c8dcSSimon Schubert static int traceframe_number;
1445796c8dcSSimon Schubert 
1455796c8dcSSimon Schubert /* Tracepoint for last traceframe collected.  */
1465796c8dcSSimon Schubert static int tracepoint_number;
1475796c8dcSSimon Schubert 
148c50c785cSJohn Marino /* Symbol for function for last traceframe collected.  */
1495796c8dcSSimon Schubert static struct symbol *traceframe_fun;
1505796c8dcSSimon Schubert 
151c50c785cSJohn Marino /* Symtab and line for last traceframe collected.  */
1525796c8dcSSimon Schubert static struct symtab_and_line traceframe_sal;
1535796c8dcSSimon Schubert 
154c50c785cSJohn Marino /* The traceframe info of the current traceframe.  NULL if we haven't
155c50c785cSJohn Marino    yet attempted to fetch it, or if the target does not support
156c50c785cSJohn Marino    fetching this object, or if we're not inspecting a traceframe
157c50c785cSJohn Marino    presently.  */
158c50c785cSJohn Marino static struct traceframe_info *traceframe_info;
159c50c785cSJohn Marino 
160c50c785cSJohn Marino /* Tracing command lists.  */
1615796c8dcSSimon Schubert static struct cmd_list_element *tfindlist;
1625796c8dcSSimon Schubert 
163cf7f2e2dSJohn Marino /* List of expressions to collect by default at each tracepoint hit.  */
164cf7f2e2dSJohn Marino char *default_collect = "";
165cf7f2e2dSJohn Marino 
166cf7f2e2dSJohn Marino static int disconnected_tracing;
167cf7f2e2dSJohn Marino 
168cf7f2e2dSJohn Marino /* This variable controls whether we ask the target for a linear or
169cf7f2e2dSJohn Marino    circular trace buffer.  */
170cf7f2e2dSJohn Marino 
171cf7f2e2dSJohn Marino static int circular_trace_buffer;
172cf7f2e2dSJohn Marino 
173*ef5ccd6cSJohn Marino /* This variable is the requested trace buffer size, or -1 to indicate
174*ef5ccd6cSJohn Marino    that we don't care and leave it up to the target to set a size.  */
175*ef5ccd6cSJohn Marino 
176*ef5ccd6cSJohn Marino static int trace_buffer_size = -1;
177*ef5ccd6cSJohn Marino 
178a45ae5f8SJohn Marino /* Textual notes applying to the current and/or future trace runs.  */
179a45ae5f8SJohn Marino 
180a45ae5f8SJohn Marino char *trace_user = NULL;
181a45ae5f8SJohn Marino 
182a45ae5f8SJohn Marino /* Textual notes applying to the current and/or future trace runs.  */
183a45ae5f8SJohn Marino 
184a45ae5f8SJohn Marino char *trace_notes = NULL;
185a45ae5f8SJohn Marino 
186a45ae5f8SJohn Marino /* Textual notes applying to the stopping of a trace.  */
187a45ae5f8SJohn Marino 
188a45ae5f8SJohn Marino char *trace_stop_notes = NULL;
189a45ae5f8SJohn Marino 
1905796c8dcSSimon Schubert /* ======= Important command functions: ======= */
1915796c8dcSSimon Schubert static void trace_actions_command (char *, int);
1925796c8dcSSimon Schubert static void trace_start_command (char *, int);
1935796c8dcSSimon Schubert static void trace_stop_command (char *, int);
1945796c8dcSSimon Schubert static void trace_status_command (char *, int);
1955796c8dcSSimon Schubert static void trace_find_command (char *, int);
1965796c8dcSSimon Schubert static void trace_find_pc_command (char *, int);
1975796c8dcSSimon Schubert static void trace_find_tracepoint_command (char *, int);
1985796c8dcSSimon Schubert static void trace_find_line_command (char *, int);
1995796c8dcSSimon Schubert static void trace_find_range_command (char *, int);
2005796c8dcSSimon Schubert static void trace_find_outside_command (char *, int);
2015796c8dcSSimon Schubert static void trace_dump_command (char *, int);
2025796c8dcSSimon Schubert 
2035796c8dcSSimon Schubert /* support routines */
2045796c8dcSSimon Schubert 
2055796c8dcSSimon Schubert struct collection_list;
2065796c8dcSSimon Schubert static void add_aexpr (struct collection_list *, struct agent_expr *);
2075796c8dcSSimon Schubert static char *mem2hex (gdb_byte *, char *, int);
2085796c8dcSSimon Schubert static void add_register (struct collection_list *collection,
2095796c8dcSSimon Schubert 			  unsigned int regno);
210cf7f2e2dSJohn Marino 
211cf7f2e2dSJohn Marino static void free_uploaded_tps (struct uploaded_tp **utpp);
212cf7f2e2dSJohn Marino static void free_uploaded_tsvs (struct uploaded_tsv **utsvp);
213cf7f2e2dSJohn Marino 
2145796c8dcSSimon Schubert 
2155796c8dcSSimon Schubert extern void _initialize_tracepoint (void);
2165796c8dcSSimon Schubert 
217cf7f2e2dSJohn Marino static struct trace_status trace_status;
2185796c8dcSSimon Schubert 
219cf7f2e2dSJohn Marino char *stop_reason_names[] = {
220cf7f2e2dSJohn Marino   "tunknown",
221cf7f2e2dSJohn Marino   "tnotrun",
222cf7f2e2dSJohn Marino   "tstop",
223cf7f2e2dSJohn Marino   "tfull",
224cf7f2e2dSJohn Marino   "tdisconnected",
225cf7f2e2dSJohn Marino   "tpasscount",
226cf7f2e2dSJohn Marino   "terror"
227cf7f2e2dSJohn Marino };
2285796c8dcSSimon Schubert 
229cf7f2e2dSJohn Marino struct trace_status *
current_trace_status(void)230c50c785cSJohn Marino current_trace_status (void)
2315796c8dcSSimon Schubert {
232cf7f2e2dSJohn Marino   return &trace_status;
2335796c8dcSSimon Schubert }
2345796c8dcSSimon Schubert 
235c50c785cSJohn Marino /* Destroy INFO.  */
236c50c785cSJohn Marino 
237c50c785cSJohn Marino static void
free_traceframe_info(struct traceframe_info * info)238c50c785cSJohn Marino free_traceframe_info (struct traceframe_info *info)
239c50c785cSJohn Marino {
240c50c785cSJohn Marino   if (info != NULL)
241c50c785cSJohn Marino     {
242c50c785cSJohn Marino       VEC_free (mem_range_s, info->memory);
243c50c785cSJohn Marino 
244c50c785cSJohn Marino       xfree (info);
245c50c785cSJohn Marino     }
246c50c785cSJohn Marino }
247c50c785cSJohn Marino 
248a45ae5f8SJohn Marino /* Free and clear the traceframe info cache of the current
249c50c785cSJohn Marino    traceframe.  */
250c50c785cSJohn Marino 
251c50c785cSJohn Marino static void
clear_traceframe_info(void)252c50c785cSJohn Marino clear_traceframe_info (void)
253c50c785cSJohn Marino {
254c50c785cSJohn Marino   free_traceframe_info (traceframe_info);
255c50c785cSJohn Marino   traceframe_info = NULL;
256c50c785cSJohn Marino }
257c50c785cSJohn Marino 
2585796c8dcSSimon Schubert /* Set traceframe number to NUM.  */
2595796c8dcSSimon Schubert static void
set_traceframe_num(int num)2605796c8dcSSimon Schubert set_traceframe_num (int num)
2615796c8dcSSimon Schubert {
2625796c8dcSSimon Schubert   traceframe_number = num;
2635796c8dcSSimon Schubert   set_internalvar_integer (lookup_internalvar ("trace_frame"), num);
2645796c8dcSSimon Schubert }
2655796c8dcSSimon Schubert 
2665796c8dcSSimon Schubert /* Set tracepoint number to NUM.  */
2675796c8dcSSimon Schubert static void
set_tracepoint_num(int num)2685796c8dcSSimon Schubert set_tracepoint_num (int num)
2695796c8dcSSimon Schubert {
2705796c8dcSSimon Schubert   tracepoint_number = num;
2715796c8dcSSimon Schubert   set_internalvar_integer (lookup_internalvar ("tracepoint"), num);
2725796c8dcSSimon Schubert }
2735796c8dcSSimon Schubert 
2745796c8dcSSimon Schubert /* Set externally visible debug variables for querying/printing
275c50c785cSJohn Marino    the traceframe context (line, function, file).  */
2765796c8dcSSimon Schubert 
2775796c8dcSSimon Schubert static void
set_traceframe_context(struct frame_info * trace_frame)2785796c8dcSSimon Schubert set_traceframe_context (struct frame_info *trace_frame)
2795796c8dcSSimon Schubert {
2805796c8dcSSimon Schubert   CORE_ADDR trace_pc;
2815796c8dcSSimon Schubert 
2825796c8dcSSimon Schubert   /* Save as globals for internal use.  */
283c50c785cSJohn Marino   if (trace_frame != NULL
284c50c785cSJohn Marino       && get_frame_pc_if_available (trace_frame, &trace_pc))
285c50c785cSJohn Marino     {
2865796c8dcSSimon Schubert       traceframe_sal = find_pc_line (trace_pc, 0);
2875796c8dcSSimon Schubert       traceframe_fun = find_pc_function (trace_pc);
2885796c8dcSSimon Schubert 
2895796c8dcSSimon Schubert       /* Save linenumber as "$trace_line", a debugger variable visible to
2905796c8dcSSimon Schubert 	 users.  */
2915796c8dcSSimon Schubert       set_internalvar_integer (lookup_internalvar ("trace_line"),
2925796c8dcSSimon Schubert 			       traceframe_sal.line);
293c50c785cSJohn Marino     }
294c50c785cSJohn Marino   else
295c50c785cSJohn Marino     {
296c50c785cSJohn Marino       init_sal (&traceframe_sal);
297c50c785cSJohn Marino       traceframe_fun = NULL;
298c50c785cSJohn Marino       set_internalvar_integer (lookup_internalvar ("trace_line"), -1);
299c50c785cSJohn Marino     }
3005796c8dcSSimon Schubert 
3015796c8dcSSimon Schubert   /* Save func name as "$trace_func", a debugger variable visible to
3025796c8dcSSimon Schubert      users.  */
3035796c8dcSSimon Schubert   if (traceframe_fun == NULL
3045796c8dcSSimon Schubert       || SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL)
3055796c8dcSSimon Schubert     clear_internalvar (lookup_internalvar ("trace_func"));
3065796c8dcSSimon Schubert   else
3075796c8dcSSimon Schubert     set_internalvar_string (lookup_internalvar ("trace_func"),
3085796c8dcSSimon Schubert 			    SYMBOL_LINKAGE_NAME (traceframe_fun));
3095796c8dcSSimon Schubert 
3105796c8dcSSimon Schubert   /* Save file name as "$trace_file", a debugger variable visible to
3115796c8dcSSimon Schubert      users.  */
312*ef5ccd6cSJohn Marino   if (traceframe_sal.symtab == NULL)
3135796c8dcSSimon Schubert     clear_internalvar (lookup_internalvar ("trace_file"));
3145796c8dcSSimon Schubert   else
3155796c8dcSSimon Schubert     set_internalvar_string (lookup_internalvar ("trace_file"),
316*ef5ccd6cSJohn Marino 			symtab_to_filename_for_display (traceframe_sal.symtab));
3175796c8dcSSimon Schubert }
3185796c8dcSSimon Schubert 
319cf7f2e2dSJohn Marino /* Create a new trace state variable with the given name.  */
3205796c8dcSSimon Schubert 
321cf7f2e2dSJohn Marino struct trace_state_variable *
create_trace_state_variable(const char * name)322cf7f2e2dSJohn Marino create_trace_state_variable (const char *name)
323cf7f2e2dSJohn Marino {
324cf7f2e2dSJohn Marino   struct trace_state_variable tsv;
325cf7f2e2dSJohn Marino 
326cf7f2e2dSJohn Marino   memset (&tsv, 0, sizeof (tsv));
327cf7f2e2dSJohn Marino   tsv.name = xstrdup (name);
328cf7f2e2dSJohn Marino   tsv.number = next_tsv_number++;
329cf7f2e2dSJohn Marino   return VEC_safe_push (tsv_s, tvariables, &tsv);
330cf7f2e2dSJohn Marino }
331cf7f2e2dSJohn Marino 
332cf7f2e2dSJohn Marino /* Look for a trace state variable of the given name.  */
333cf7f2e2dSJohn Marino 
334cf7f2e2dSJohn Marino struct trace_state_variable *
find_trace_state_variable(const char * name)335cf7f2e2dSJohn Marino find_trace_state_variable (const char *name)
336cf7f2e2dSJohn Marino {
337cf7f2e2dSJohn Marino   struct trace_state_variable *tsv;
338cf7f2e2dSJohn Marino   int ix;
339cf7f2e2dSJohn Marino 
340cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
341cf7f2e2dSJohn Marino     if (strcmp (name, tsv->name) == 0)
342cf7f2e2dSJohn Marino       return tsv;
343cf7f2e2dSJohn Marino 
344cf7f2e2dSJohn Marino   return NULL;
345cf7f2e2dSJohn Marino }
346cf7f2e2dSJohn Marino 
347*ef5ccd6cSJohn Marino static void
delete_trace_state_variable(const char * name)348cf7f2e2dSJohn Marino delete_trace_state_variable (const char *name)
349cf7f2e2dSJohn Marino {
350cf7f2e2dSJohn Marino   struct trace_state_variable *tsv;
351cf7f2e2dSJohn Marino   int ix;
352cf7f2e2dSJohn Marino 
353cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
354cf7f2e2dSJohn Marino     if (strcmp (name, tsv->name) == 0)
355cf7f2e2dSJohn Marino       {
356*ef5ccd6cSJohn Marino 	observer_notify_tsv_deleted (tsv);
357*ef5ccd6cSJohn Marino 
358cf7f2e2dSJohn Marino 	xfree ((void *)tsv->name);
359cf7f2e2dSJohn Marino 	VEC_unordered_remove (tsv_s, tvariables, ix);
360*ef5ccd6cSJohn Marino 
361cf7f2e2dSJohn Marino 	return;
362cf7f2e2dSJohn Marino       }
363cf7f2e2dSJohn Marino 
364cf7f2e2dSJohn Marino   warning (_("No trace variable named \"$%s\", not deleting"), name);
365cf7f2e2dSJohn Marino }
366cf7f2e2dSJohn Marino 
367*ef5ccd6cSJohn Marino /* Throws an error if NAME is not valid syntax for a trace state
368*ef5ccd6cSJohn Marino    variable's name.  */
369*ef5ccd6cSJohn Marino 
370*ef5ccd6cSJohn Marino void
validate_trace_state_variable_name(const char * name)371*ef5ccd6cSJohn Marino validate_trace_state_variable_name (const char *name)
372*ef5ccd6cSJohn Marino {
373*ef5ccd6cSJohn Marino   const char *p;
374*ef5ccd6cSJohn Marino 
375*ef5ccd6cSJohn Marino   if (*name == '\0')
376*ef5ccd6cSJohn Marino     error (_("Must supply a non-empty variable name"));
377*ef5ccd6cSJohn Marino 
378*ef5ccd6cSJohn Marino   /* All digits in the name is reserved for value history
379*ef5ccd6cSJohn Marino      references.  */
380*ef5ccd6cSJohn Marino   for (p = name; isdigit (*p); p++)
381*ef5ccd6cSJohn Marino     ;
382*ef5ccd6cSJohn Marino   if (*p == '\0')
383*ef5ccd6cSJohn Marino     error (_("$%s is not a valid trace state variable name"), name);
384*ef5ccd6cSJohn Marino 
385*ef5ccd6cSJohn Marino   for (p = name; isalnum (*p) || *p == '_'; p++)
386*ef5ccd6cSJohn Marino     ;
387*ef5ccd6cSJohn Marino   if (*p != '\0')
388*ef5ccd6cSJohn Marino     error (_("$%s is not a valid trace state variable name"), name);
389*ef5ccd6cSJohn Marino }
390*ef5ccd6cSJohn Marino 
391cf7f2e2dSJohn Marino /* The 'tvariable' command collects a name and optional expression to
392cf7f2e2dSJohn Marino    evaluate into an initial value.  */
393cf7f2e2dSJohn Marino 
394*ef5ccd6cSJohn Marino static void
trace_variable_command(char * args,int from_tty)395cf7f2e2dSJohn Marino trace_variable_command (char *args, int from_tty)
396cf7f2e2dSJohn Marino {
397cf7f2e2dSJohn Marino   struct cleanup *old_chain;
398cf7f2e2dSJohn Marino   LONGEST initval = 0;
399cf7f2e2dSJohn Marino   struct trace_state_variable *tsv;
400*ef5ccd6cSJohn Marino   char *name, *p;
401cf7f2e2dSJohn Marino 
402cf7f2e2dSJohn Marino   if (!args || !*args)
403*ef5ccd6cSJohn Marino     error_no_arg (_("Syntax is $NAME [ = EXPR ]"));
404cf7f2e2dSJohn Marino 
405cf7f2e2dSJohn Marino   /* Only allow two syntaxes; "$name" and "$name=value".  */
406*ef5ccd6cSJohn Marino   p = skip_spaces (args);
407*ef5ccd6cSJohn Marino 
408*ef5ccd6cSJohn Marino   if (*p++ != '$')
409*ef5ccd6cSJohn Marino     error (_("Name of trace variable should start with '$'"));
410*ef5ccd6cSJohn Marino 
411*ef5ccd6cSJohn Marino   name = p;
412*ef5ccd6cSJohn Marino   while (isalnum (*p) || *p == '_')
413*ef5ccd6cSJohn Marino     p++;
414*ef5ccd6cSJohn Marino   name = savestring (name, p - name);
415*ef5ccd6cSJohn Marino   old_chain = make_cleanup (xfree, name);
416*ef5ccd6cSJohn Marino 
417*ef5ccd6cSJohn Marino   p = skip_spaces (p);
418*ef5ccd6cSJohn Marino   if (*p != '=' && *p != '\0')
419cf7f2e2dSJohn Marino     error (_("Syntax must be $NAME [ = EXPR ]"));
420cf7f2e2dSJohn Marino 
421*ef5ccd6cSJohn Marino   validate_trace_state_variable_name (name);
422cf7f2e2dSJohn Marino 
423*ef5ccd6cSJohn Marino   if (*p == '=')
424*ef5ccd6cSJohn Marino     initval = value_as_long (parse_and_eval (++p));
425cf7f2e2dSJohn Marino 
426cf7f2e2dSJohn Marino   /* If the variable already exists, just change its initial value.  */
427*ef5ccd6cSJohn Marino   tsv = find_trace_state_variable (name);
428cf7f2e2dSJohn Marino   if (tsv)
429cf7f2e2dSJohn Marino     {
430*ef5ccd6cSJohn Marino       if (tsv->initial_value != initval)
431*ef5ccd6cSJohn Marino 	{
432cf7f2e2dSJohn Marino 	  tsv->initial_value = initval;
433*ef5ccd6cSJohn Marino 	  observer_notify_tsv_modified (tsv);
434*ef5ccd6cSJohn Marino 	}
435c50c785cSJohn Marino       printf_filtered (_("Trace state variable $%s "
436c50c785cSJohn Marino 			 "now has initial value %s.\n"),
437cf7f2e2dSJohn Marino 		       tsv->name, plongest (tsv->initial_value));
438cf7f2e2dSJohn Marino       do_cleanups (old_chain);
439cf7f2e2dSJohn Marino       return;
440cf7f2e2dSJohn Marino     }
441cf7f2e2dSJohn Marino 
442cf7f2e2dSJohn Marino   /* Create a new variable.  */
443*ef5ccd6cSJohn Marino   tsv = create_trace_state_variable (name);
444cf7f2e2dSJohn Marino   tsv->initial_value = initval;
445cf7f2e2dSJohn Marino 
446*ef5ccd6cSJohn Marino   observer_notify_tsv_created (tsv);
447*ef5ccd6cSJohn Marino 
448c50c785cSJohn Marino   printf_filtered (_("Trace state variable $%s "
449c50c785cSJohn Marino 		     "created, with initial value %s.\n"),
450cf7f2e2dSJohn Marino 		   tsv->name, plongest (tsv->initial_value));
451cf7f2e2dSJohn Marino 
452cf7f2e2dSJohn Marino   do_cleanups (old_chain);
453cf7f2e2dSJohn Marino }
454cf7f2e2dSJohn Marino 
455*ef5ccd6cSJohn Marino static void
delete_trace_variable_command(char * args,int from_tty)456cf7f2e2dSJohn Marino delete_trace_variable_command (char *args, int from_tty)
457cf7f2e2dSJohn Marino {
458cf7f2e2dSJohn Marino   int ix;
459cf7f2e2dSJohn Marino   char **argv;
460cf7f2e2dSJohn Marino   struct cleanup *back_to;
461cf7f2e2dSJohn Marino 
462cf7f2e2dSJohn Marino   if (args == NULL)
463cf7f2e2dSJohn Marino     {
464cf7f2e2dSJohn Marino       if (query (_("Delete all trace state variables? ")))
465cf7f2e2dSJohn Marino 	VEC_free (tsv_s, tvariables);
466cf7f2e2dSJohn Marino       dont_repeat ();
467*ef5ccd6cSJohn Marino       observer_notify_tsv_deleted (NULL);
468cf7f2e2dSJohn Marino       return;
469cf7f2e2dSJohn Marino     }
470cf7f2e2dSJohn Marino 
471cf7f2e2dSJohn Marino   argv = gdb_buildargv (args);
472cf7f2e2dSJohn Marino   back_to = make_cleanup_freeargv (argv);
473cf7f2e2dSJohn Marino 
474cf7f2e2dSJohn Marino   for (ix = 0; argv[ix] != NULL; ix++)
475cf7f2e2dSJohn Marino     {
476cf7f2e2dSJohn Marino       if (*argv[ix] == '$')
477cf7f2e2dSJohn Marino 	delete_trace_state_variable (argv[ix] + 1);
478cf7f2e2dSJohn Marino       else
479cf7f2e2dSJohn Marino 	warning (_("Name \"%s\" not prefixed with '$', ignoring"), argv[ix]);
480cf7f2e2dSJohn Marino     }
481cf7f2e2dSJohn Marino 
482cf7f2e2dSJohn Marino   do_cleanups (back_to);
483cf7f2e2dSJohn Marino 
484cf7f2e2dSJohn Marino   dont_repeat ();
485cf7f2e2dSJohn Marino }
486cf7f2e2dSJohn Marino 
487cf7f2e2dSJohn Marino void
tvariables_info_1(void)488cf7f2e2dSJohn Marino tvariables_info_1 (void)
489cf7f2e2dSJohn Marino {
490cf7f2e2dSJohn Marino   struct trace_state_variable *tsv;
491cf7f2e2dSJohn Marino   int ix;
492cf7f2e2dSJohn Marino   int count = 0;
493cf7f2e2dSJohn Marino   struct cleanup *back_to;
494a45ae5f8SJohn Marino   struct ui_out *uiout = current_uiout;
495cf7f2e2dSJohn Marino 
496cf7f2e2dSJohn Marino   if (VEC_length (tsv_s, tvariables) == 0 && !ui_out_is_mi_like_p (uiout))
497cf7f2e2dSJohn Marino     {
498cf7f2e2dSJohn Marino       printf_filtered (_("No trace state variables.\n"));
499cf7f2e2dSJohn Marino       return;
500cf7f2e2dSJohn Marino     }
501cf7f2e2dSJohn Marino 
502cf7f2e2dSJohn Marino   /* Try to acquire values from the target.  */
503cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix, ++count)
504cf7f2e2dSJohn Marino     tsv->value_known = target_get_trace_state_variable_value (tsv->number,
505cf7f2e2dSJohn Marino 							      &(tsv->value));
506cf7f2e2dSJohn Marino 
507cf7f2e2dSJohn Marino   back_to = make_cleanup_ui_out_table_begin_end (uiout, 3,
508cf7f2e2dSJohn Marino                                                  count, "trace-variables");
509cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 15, ui_left, "name", "Name");
510cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 11, ui_left, "initial", "Initial");
511cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 11, ui_left, "current", "Current");
512cf7f2e2dSJohn Marino 
513cf7f2e2dSJohn Marino   ui_out_table_body (uiout);
514cf7f2e2dSJohn Marino 
515cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
516cf7f2e2dSJohn Marino     {
517cf7f2e2dSJohn Marino       struct cleanup *back_to2;
518cf7f2e2dSJohn Marino       char *c;
519cf7f2e2dSJohn Marino       char *name;
520cf7f2e2dSJohn Marino 
521cf7f2e2dSJohn Marino       back_to2 = make_cleanup_ui_out_tuple_begin_end (uiout, "variable");
522cf7f2e2dSJohn Marino 
523cf7f2e2dSJohn Marino       name = concat ("$", tsv->name, (char *) NULL);
524cf7f2e2dSJohn Marino       make_cleanup (xfree, name);
525cf7f2e2dSJohn Marino       ui_out_field_string (uiout, "name", name);
526cf7f2e2dSJohn Marino       ui_out_field_string (uiout, "initial", plongest (tsv->initial_value));
527cf7f2e2dSJohn Marino 
528cf7f2e2dSJohn Marino       if (tsv->value_known)
529cf7f2e2dSJohn Marino         c = plongest (tsv->value);
530cf7f2e2dSJohn Marino       else if (ui_out_is_mi_like_p (uiout))
531cf7f2e2dSJohn Marino         /* For MI, we prefer not to use magic string constants, but rather
532cf7f2e2dSJohn Marino            omit the field completely.  The difference between unknown and
533cf7f2e2dSJohn Marino            undefined does not seem important enough to represent.  */
534cf7f2e2dSJohn Marino         c = NULL;
535cf7f2e2dSJohn Marino       else if (current_trace_status ()->running || traceframe_number >= 0)
536cf7f2e2dSJohn Marino 	/* The value is/was defined, but we don't have it.  */
537cf7f2e2dSJohn Marino         c = "<unknown>";
538cf7f2e2dSJohn Marino       else
539cf7f2e2dSJohn Marino 	/* It is not meaningful to ask about the value.  */
540cf7f2e2dSJohn Marino         c = "<undefined>";
541cf7f2e2dSJohn Marino       if (c)
542cf7f2e2dSJohn Marino         ui_out_field_string (uiout, "current", c);
543cf7f2e2dSJohn Marino       ui_out_text (uiout, "\n");
544cf7f2e2dSJohn Marino 
545cf7f2e2dSJohn Marino       do_cleanups (back_to2);
546cf7f2e2dSJohn Marino     }
547cf7f2e2dSJohn Marino 
548cf7f2e2dSJohn Marino   do_cleanups (back_to);
549cf7f2e2dSJohn Marino }
550cf7f2e2dSJohn Marino 
551cf7f2e2dSJohn Marino /* List all the trace state variables.  */
552cf7f2e2dSJohn Marino 
553cf7f2e2dSJohn Marino static void
tvariables_info(char * args,int from_tty)554cf7f2e2dSJohn Marino tvariables_info (char *args, int from_tty)
555cf7f2e2dSJohn Marino {
556cf7f2e2dSJohn Marino   tvariables_info_1 ();
557cf7f2e2dSJohn Marino }
558cf7f2e2dSJohn Marino 
559cf7f2e2dSJohn Marino /* Stash definitions of tsvs into the given file.  */
560cf7f2e2dSJohn Marino 
561cf7f2e2dSJohn Marino void
save_trace_state_variables(struct ui_file * fp)562cf7f2e2dSJohn Marino save_trace_state_variables (struct ui_file *fp)
563cf7f2e2dSJohn Marino {
564cf7f2e2dSJohn Marino   struct trace_state_variable *tsv;
565cf7f2e2dSJohn Marino   int ix;
566cf7f2e2dSJohn Marino 
567cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
568cf7f2e2dSJohn Marino     {
569cf7f2e2dSJohn Marino       fprintf_unfiltered (fp, "tvariable $%s", tsv->name);
570cf7f2e2dSJohn Marino       if (tsv->initial_value)
571cf7f2e2dSJohn Marino 	fprintf_unfiltered (fp, " = %s", plongest (tsv->initial_value));
572cf7f2e2dSJohn Marino       fprintf_unfiltered (fp, "\n");
573cf7f2e2dSJohn Marino     }
574cf7f2e2dSJohn Marino }
575cf7f2e2dSJohn Marino 
576cf7f2e2dSJohn Marino /* ACTIONS functions: */
5775796c8dcSSimon Schubert 
5785796c8dcSSimon Schubert /* The three functions:
5795796c8dcSSimon Schubert    collect_pseudocommand,
5805796c8dcSSimon Schubert    while_stepping_pseudocommand, and
5815796c8dcSSimon Schubert    end_actions_pseudocommand
5825796c8dcSSimon Schubert    are placeholders for "commands" that are actually ONLY to be used
5835796c8dcSSimon Schubert    within a tracepoint action list.  If the actual function is ever called,
5845796c8dcSSimon Schubert    it means that somebody issued the "command" at the top level,
5855796c8dcSSimon Schubert    which is always an error.  */
5865796c8dcSSimon Schubert 
587*ef5ccd6cSJohn Marino static void
end_actions_pseudocommand(char * args,int from_tty)5885796c8dcSSimon Schubert end_actions_pseudocommand (char *args, int from_tty)
5895796c8dcSSimon Schubert {
5905796c8dcSSimon Schubert   error (_("This command cannot be used at the top level."));
5915796c8dcSSimon Schubert }
5925796c8dcSSimon Schubert 
593*ef5ccd6cSJohn Marino static void
while_stepping_pseudocommand(char * args,int from_tty)5945796c8dcSSimon Schubert while_stepping_pseudocommand (char *args, int from_tty)
5955796c8dcSSimon Schubert {
5965796c8dcSSimon Schubert   error (_("This command can only be used in a tracepoint actions list."));
5975796c8dcSSimon Schubert }
5985796c8dcSSimon Schubert 
5995796c8dcSSimon Schubert static void
collect_pseudocommand(char * args,int from_tty)6005796c8dcSSimon Schubert collect_pseudocommand (char *args, int from_tty)
6015796c8dcSSimon Schubert {
6025796c8dcSSimon Schubert   error (_("This command can only be used in a tracepoint actions list."));
6035796c8dcSSimon Schubert }
6045796c8dcSSimon Schubert 
605cf7f2e2dSJohn Marino static void
teval_pseudocommand(char * args,int from_tty)606cf7f2e2dSJohn Marino teval_pseudocommand (char *args, int from_tty)
607cf7f2e2dSJohn Marino {
608cf7f2e2dSJohn Marino   error (_("This command can only be used in a tracepoint actions list."));
609cf7f2e2dSJohn Marino }
610cf7f2e2dSJohn Marino 
611a45ae5f8SJohn Marino /* Parse any collection options, such as /s for strings.  */
612a45ae5f8SJohn Marino 
613a45ae5f8SJohn Marino char *
decode_agent_options(char * exp)614a45ae5f8SJohn Marino decode_agent_options (char *exp)
615a45ae5f8SJohn Marino {
616a45ae5f8SJohn Marino   struct value_print_options opts;
617a45ae5f8SJohn Marino 
618a45ae5f8SJohn Marino   if (*exp != '/')
619a45ae5f8SJohn Marino     return exp;
620a45ae5f8SJohn Marino 
621a45ae5f8SJohn Marino   /* Call this to borrow the print elements default for collection
622a45ae5f8SJohn Marino      size.  */
623a45ae5f8SJohn Marino   get_user_print_options (&opts);
624a45ae5f8SJohn Marino 
625a45ae5f8SJohn Marino   exp++;
626a45ae5f8SJohn Marino   if (*exp == 's')
627a45ae5f8SJohn Marino     {
628a45ae5f8SJohn Marino       if (target_supports_string_tracing ())
629a45ae5f8SJohn Marino 	{
630a45ae5f8SJohn Marino 	  /* Allow an optional decimal number giving an explicit maximum
631a45ae5f8SJohn Marino 	     string length, defaulting it to the "print elements" value;
632a45ae5f8SJohn Marino 	     so "collect/s80 mystr" gets at most 80 bytes of string.  */
633a45ae5f8SJohn Marino 	  trace_string_kludge = opts.print_max;
634a45ae5f8SJohn Marino 	  exp++;
635a45ae5f8SJohn Marino 	  if (*exp >= '0' && *exp <= '9')
636a45ae5f8SJohn Marino 	    trace_string_kludge = atoi (exp);
637a45ae5f8SJohn Marino 	  while (*exp >= '0' && *exp <= '9')
638a45ae5f8SJohn Marino 	    exp++;
639a45ae5f8SJohn Marino 	}
640a45ae5f8SJohn Marino       else
641a45ae5f8SJohn Marino 	error (_("Target does not support \"/s\" option for string tracing."));
642a45ae5f8SJohn Marino     }
643a45ae5f8SJohn Marino   else
644a45ae5f8SJohn Marino     error (_("Undefined collection format \"%c\"."), *exp);
645a45ae5f8SJohn Marino 
646a45ae5f8SJohn Marino   exp = skip_spaces (exp);
647a45ae5f8SJohn Marino 
648a45ae5f8SJohn Marino   return exp;
649a45ae5f8SJohn Marino }
650a45ae5f8SJohn Marino 
6515796c8dcSSimon Schubert /* Enter a list of actions for a tracepoint.  */
6525796c8dcSSimon Schubert static void
trace_actions_command(char * args,int from_tty)6535796c8dcSSimon Schubert trace_actions_command (char *args, int from_tty)
6545796c8dcSSimon Schubert {
655a45ae5f8SJohn Marino   struct tracepoint *t;
656cf7f2e2dSJohn Marino   struct command_line *l;
6575796c8dcSSimon Schubert 
658c50c785cSJohn Marino   t = get_tracepoint_by_number (&args, NULL, 1);
6595796c8dcSSimon Schubert   if (t)
6605796c8dcSSimon Schubert     {
661cf7f2e2dSJohn Marino       char *tmpbuf =
662cf7f2e2dSJohn Marino 	xstrprintf ("Enter actions for tracepoint %d, one per line.",
663a45ae5f8SJohn Marino 		    t->base.number);
664cf7f2e2dSJohn Marino       struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
6655796c8dcSSimon Schubert 
666c50c785cSJohn Marino       l = read_command_lines (tmpbuf, from_tty, 1,
667c50c785cSJohn Marino 			      check_tracepoint_command, t);
668cf7f2e2dSJohn Marino       do_cleanups (cleanups);
669a45ae5f8SJohn Marino       breakpoint_set_commands (&t->base, l);
6705796c8dcSSimon Schubert     }
6715796c8dcSSimon Schubert   /* else just return */
6725796c8dcSSimon Schubert }
6735796c8dcSSimon Schubert 
674cf7f2e2dSJohn Marino /* Report the results of checking the agent expression, as errors or
675cf7f2e2dSJohn Marino    internal errors.  */
676cf7f2e2dSJohn Marino 
6775796c8dcSSimon Schubert static void
report_agent_reqs_errors(struct agent_expr * aexpr)678cf7f2e2dSJohn Marino report_agent_reqs_errors (struct agent_expr *aexpr)
6795796c8dcSSimon Schubert {
680cf7f2e2dSJohn Marino   /* All of the "flaws" are serious bytecode generation issues that
681cf7f2e2dSJohn Marino      should never occur.  */
682cf7f2e2dSJohn Marino   if (aexpr->flaw != agent_flaw_none)
683cf7f2e2dSJohn Marino     internal_error (__FILE__, __LINE__, _("expression is malformed"));
6845796c8dcSSimon Schubert 
685cf7f2e2dSJohn Marino   /* If analysis shows a stack underflow, GDB must have done something
686cf7f2e2dSJohn Marino      badly wrong in its bytecode generation.  */
687cf7f2e2dSJohn Marino   if (aexpr->min_height < 0)
688cf7f2e2dSJohn Marino     internal_error (__FILE__, __LINE__,
689cf7f2e2dSJohn Marino 		    _("expression has min height < 0"));
6905796c8dcSSimon Schubert 
691cf7f2e2dSJohn Marino   /* Issue this error if the stack is predicted to get too deep.  The
692cf7f2e2dSJohn Marino      limit is rather arbitrary; a better scheme might be for the
693cf7f2e2dSJohn Marino      target to report how much stack it will have available.  The
694cf7f2e2dSJohn Marino      depth roughly corresponds to parenthesization, so a limit of 20
695cf7f2e2dSJohn Marino      amounts to 20 levels of expression nesting, which is actually
696cf7f2e2dSJohn Marino      a pretty big hairy expression.  */
697cf7f2e2dSJohn Marino   if (aexpr->max_height > 20)
698cf7f2e2dSJohn Marino     error (_("Expression is too complicated."));
6995796c8dcSSimon Schubert }
7005796c8dcSSimon Schubert 
7015796c8dcSSimon Schubert /* worker function */
702cf7f2e2dSJohn Marino void
validate_actionline(char ** line,struct breakpoint * b)703a45ae5f8SJohn Marino validate_actionline (char **line, struct breakpoint *b)
7045796c8dcSSimon Schubert {
7055796c8dcSSimon Schubert   struct cmd_list_element *c;
7065796c8dcSSimon Schubert   struct expression *exp = NULL;
7075796c8dcSSimon Schubert   struct cleanup *old_chain = NULL;
708cf7f2e2dSJohn Marino   char *p, *tmp_p;
709cf7f2e2dSJohn Marino   struct bp_location *loc;
710cf7f2e2dSJohn Marino   struct agent_expr *aexpr;
711a45ae5f8SJohn Marino   struct tracepoint *t = (struct tracepoint *) b;
7125796c8dcSSimon Schubert 
713c50c785cSJohn Marino   /* If EOF is typed, *line is NULL.  */
7145796c8dcSSimon Schubert   if (*line == NULL)
715cf7f2e2dSJohn Marino     return;
7165796c8dcSSimon Schubert 
717*ef5ccd6cSJohn Marino   p = skip_spaces (*line);
7185796c8dcSSimon Schubert 
7195796c8dcSSimon Schubert   /* Symbol lookup etc.  */
7205796c8dcSSimon Schubert   if (*p == '\0')	/* empty line: just prompt for another line.  */
721cf7f2e2dSJohn Marino     return;
7225796c8dcSSimon Schubert 
7235796c8dcSSimon Schubert   if (*p == '#')		/* comment line */
724cf7f2e2dSJohn Marino     return;
7255796c8dcSSimon Schubert 
7265796c8dcSSimon Schubert   c = lookup_cmd (&p, cmdlist, "", -1, 1);
7275796c8dcSSimon Schubert   if (c == 0)
728cf7f2e2dSJohn Marino     error (_("`%s' is not a tracepoint action, or is ambiguous."), p);
7295796c8dcSSimon Schubert 
7305796c8dcSSimon Schubert   if (cmd_cfunc_eq (c, collect_pseudocommand))
7315796c8dcSSimon Schubert     {
732a45ae5f8SJohn Marino       trace_string_kludge = 0;
733a45ae5f8SJohn Marino       if (*p == '/')
734a45ae5f8SJohn Marino 	p = decode_agent_options (p);
735a45ae5f8SJohn Marino 
7365796c8dcSSimon Schubert       do
737c50c785cSJohn Marino 	{			/* Repeat over a comma-separated list.  */
738c50c785cSJohn Marino 	  QUIT;			/* Allow user to bail out with ^C.  */
739*ef5ccd6cSJohn Marino 	  p = skip_spaces (p);
7405796c8dcSSimon Schubert 
741c50c785cSJohn Marino 	  if (*p == '$')	/* Look for special pseudo-symbols.  */
7425796c8dcSSimon Schubert 	    {
743cf7f2e2dSJohn Marino 	      if (0 == strncasecmp ("reg", p + 1, 3)
744cf7f2e2dSJohn Marino 		  || 0 == strncasecmp ("arg", p + 1, 3)
745cf7f2e2dSJohn Marino 		  || 0 == strncasecmp ("loc", p + 1, 3)
746a45ae5f8SJohn Marino 		  || 0 == strncasecmp ("_ret", p + 1, 4)
747cf7f2e2dSJohn Marino 		  || 0 == strncasecmp ("_sdata", p + 1, 6))
7485796c8dcSSimon Schubert 		{
7495796c8dcSSimon Schubert 		  p = strchr (p, ',');
7505796c8dcSSimon Schubert 		  continue;
7515796c8dcSSimon Schubert 		}
7525796c8dcSSimon Schubert 	      /* else fall thru, treat p as an expression and parse it!  */
7535796c8dcSSimon Schubert 	    }
754cf7f2e2dSJohn Marino 	  tmp_p = p;
755a45ae5f8SJohn Marino 	  for (loc = t->base.loc; loc; loc = loc->next)
756cf7f2e2dSJohn Marino 	    {
757*ef5ccd6cSJohn Marino 	      const char *q;
758*ef5ccd6cSJohn Marino 
759*ef5ccd6cSJohn Marino 	      q = tmp_p;
760*ef5ccd6cSJohn Marino 	      exp = parse_exp_1 (&q, loc->address,
761*ef5ccd6cSJohn Marino 				 block_for_pc (loc->address), 1);
762*ef5ccd6cSJohn Marino 	      p = (char *) q;
7635796c8dcSSimon Schubert 	      old_chain = make_cleanup (free_current_contents, &exp);
7645796c8dcSSimon Schubert 
7655796c8dcSSimon Schubert 	      if (exp->elts[0].opcode == OP_VAR_VALUE)
7665796c8dcSSimon Schubert 		{
7675796c8dcSSimon Schubert 		  if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
7685796c8dcSSimon Schubert 		    {
769*ef5ccd6cSJohn Marino 		      error (_("constant `%s' (value %s) "
770c50c785cSJohn Marino 			       "will not be collected."),
7715796c8dcSSimon Schubert 			     SYMBOL_PRINT_NAME (exp->elts[2].symbol),
772*ef5ccd6cSJohn Marino 			     plongest (SYMBOL_VALUE (exp->elts[2].symbol)));
7735796c8dcSSimon Schubert 		    }
774c50c785cSJohn Marino 		  else if (SYMBOL_CLASS (exp->elts[2].symbol)
775c50c785cSJohn Marino 			   == LOC_OPTIMIZED_OUT)
7765796c8dcSSimon Schubert 		    {
777c50c785cSJohn Marino 		      error (_("`%s' is optimized away "
778c50c785cSJohn Marino 			       "and cannot be collected."),
7795796c8dcSSimon Schubert 			     SYMBOL_PRINT_NAME (exp->elts[2].symbol));
7805796c8dcSSimon Schubert 		    }
7815796c8dcSSimon Schubert 		}
7825796c8dcSSimon Schubert 
7835796c8dcSSimon Schubert 	      /* We have something to collect, make sure that the expr to
7845796c8dcSSimon Schubert 		 bytecode translator can handle it and that it's not too
7855796c8dcSSimon Schubert 		 long.  */
786cf7f2e2dSJohn Marino 	      aexpr = gen_trace_for_expr (loc->address, exp);
7875796c8dcSSimon Schubert 	      make_cleanup_free_agent_expr (aexpr);
7885796c8dcSSimon Schubert 
7895796c8dcSSimon Schubert 	      if (aexpr->len > MAX_AGENT_EXPR_LEN)
790cf7f2e2dSJohn Marino 		error (_("Expression is too complicated."));
7915796c8dcSSimon Schubert 
792cf7f2e2dSJohn Marino 	      ax_reqs (aexpr);
7935796c8dcSSimon Schubert 
794cf7f2e2dSJohn Marino 	      report_agent_reqs_errors (aexpr);
7955796c8dcSSimon Schubert 
7965796c8dcSSimon Schubert 	      do_cleanups (old_chain);
7975796c8dcSSimon Schubert 	    }
7985796c8dcSSimon Schubert 	}
799cf7f2e2dSJohn Marino       while (p && *p++ == ',');
800cf7f2e2dSJohn Marino     }
801cf7f2e2dSJohn Marino 
802cf7f2e2dSJohn Marino   else if (cmd_cfunc_eq (c, teval_pseudocommand))
803cf7f2e2dSJohn Marino     {
804cf7f2e2dSJohn Marino       do
805c50c785cSJohn Marino 	{			/* Repeat over a comma-separated list.  */
806c50c785cSJohn Marino 	  QUIT;			/* Allow user to bail out with ^C.  */
807*ef5ccd6cSJohn Marino 	  p = skip_spaces (p);
808cf7f2e2dSJohn Marino 
809cf7f2e2dSJohn Marino 	  tmp_p = p;
810a45ae5f8SJohn Marino 	  for (loc = t->base.loc; loc; loc = loc->next)
811cf7f2e2dSJohn Marino 	    {
812*ef5ccd6cSJohn Marino 	      const char *q;
813*ef5ccd6cSJohn Marino 
814*ef5ccd6cSJohn Marino 	      q = tmp_p;
815cf7f2e2dSJohn Marino 	      /* Only expressions are allowed for this action.  */
816*ef5ccd6cSJohn Marino 	      exp = parse_exp_1 (&q, loc->address,
817*ef5ccd6cSJohn Marino 				 block_for_pc (loc->address), 1);
818*ef5ccd6cSJohn Marino 	      p = (char *) q;
819cf7f2e2dSJohn Marino 	      old_chain = make_cleanup (free_current_contents, &exp);
820cf7f2e2dSJohn Marino 
821cf7f2e2dSJohn Marino 	      /* We have something to evaluate, make sure that the expr to
822cf7f2e2dSJohn Marino 		 bytecode translator can handle it and that it's not too
823cf7f2e2dSJohn Marino 		 long.  */
824cf7f2e2dSJohn Marino 	      aexpr = gen_eval_for_expr (loc->address, exp);
825cf7f2e2dSJohn Marino 	      make_cleanup_free_agent_expr (aexpr);
826cf7f2e2dSJohn Marino 
827cf7f2e2dSJohn Marino 	      if (aexpr->len > MAX_AGENT_EXPR_LEN)
828cf7f2e2dSJohn Marino 		error (_("Expression is too complicated."));
829cf7f2e2dSJohn Marino 
830cf7f2e2dSJohn Marino 	      ax_reqs (aexpr);
831cf7f2e2dSJohn Marino 	      report_agent_reqs_errors (aexpr);
832cf7f2e2dSJohn Marino 
833cf7f2e2dSJohn Marino 	      do_cleanups (old_chain);
834cf7f2e2dSJohn Marino 	    }
835cf7f2e2dSJohn Marino 	}
836cf7f2e2dSJohn Marino       while (p && *p++ == ',');
837cf7f2e2dSJohn Marino     }
838cf7f2e2dSJohn Marino 
8395796c8dcSSimon Schubert   else if (cmd_cfunc_eq (c, while_stepping_pseudocommand))
8405796c8dcSSimon Schubert     {
841c50c785cSJohn Marino       char *steparg;		/* In case warning is necessary.  */
8425796c8dcSSimon Schubert 
843*ef5ccd6cSJohn Marino       p = skip_spaces (p);
8445796c8dcSSimon Schubert       steparg = p;
8455796c8dcSSimon Schubert 
846cf7f2e2dSJohn Marino       if (*p == '\0' || (t->step_count = strtol (p, &p, 0)) == 0)
847cf7f2e2dSJohn Marino 	error (_("while-stepping step count `%s' is malformed."), *line);
8485796c8dcSSimon Schubert     }
849cf7f2e2dSJohn Marino 
8505796c8dcSSimon Schubert   else if (cmd_cfunc_eq (c, end_actions_pseudocommand))
851cf7f2e2dSJohn Marino     ;
852cf7f2e2dSJohn Marino 
8535796c8dcSSimon Schubert   else
854cf7f2e2dSJohn Marino     error (_("`%s' is not a supported tracepoint action."), *line);
8555796c8dcSSimon Schubert }
8565796c8dcSSimon Schubert 
8575796c8dcSSimon Schubert enum {
8585796c8dcSSimon Schubert   memrange_absolute = -1
8595796c8dcSSimon Schubert };
8605796c8dcSSimon Schubert 
8615796c8dcSSimon Schubert struct memrange
8625796c8dcSSimon Schubert {
8635796c8dcSSimon Schubert   int type;		/* memrange_absolute for absolute memory range,
864c50c785cSJohn Marino                            else basereg number.  */
8655796c8dcSSimon Schubert   bfd_signed_vma start;
8665796c8dcSSimon Schubert   bfd_signed_vma end;
8675796c8dcSSimon Schubert };
8685796c8dcSSimon Schubert 
8695796c8dcSSimon Schubert struct collection_list
8705796c8dcSSimon Schubert   {
8715796c8dcSSimon Schubert     unsigned char regs_mask[32];	/* room for up to 256 regs */
8725796c8dcSSimon Schubert     long listsize;
8735796c8dcSSimon Schubert     long next_memrange;
8745796c8dcSSimon Schubert     struct memrange *list;
8755796c8dcSSimon Schubert     long aexpr_listsize;	/* size of array pointed to by expr_list elt */
8765796c8dcSSimon Schubert     long next_aexpr_elt;
8775796c8dcSSimon Schubert     struct agent_expr **aexpr_list;
8785796c8dcSSimon Schubert 
879cf7f2e2dSJohn Marino     /* True is the user requested a collection of "$_sdata", "static
880cf7f2e2dSJohn Marino        tracepoint data".  */
881cf7f2e2dSJohn Marino     int strace_data;
8825796c8dcSSimon Schubert   }
8835796c8dcSSimon Schubert tracepoint_list, stepping_list;
8845796c8dcSSimon Schubert 
8855796c8dcSSimon Schubert /* MEMRANGE functions: */
8865796c8dcSSimon Schubert 
8875796c8dcSSimon Schubert static int memrange_cmp (const void *, const void *);
8885796c8dcSSimon Schubert 
889c50c785cSJohn Marino /* Compare memranges for qsort.  */
8905796c8dcSSimon Schubert static int
memrange_cmp(const void * va,const void * vb)8915796c8dcSSimon Schubert memrange_cmp (const void *va, const void *vb)
8925796c8dcSSimon Schubert {
8935796c8dcSSimon Schubert   const struct memrange *a = va, *b = vb;
8945796c8dcSSimon Schubert 
8955796c8dcSSimon Schubert   if (a->type < b->type)
8965796c8dcSSimon Schubert     return -1;
8975796c8dcSSimon Schubert   if (a->type > b->type)
8985796c8dcSSimon Schubert     return 1;
8995796c8dcSSimon Schubert   if (a->type == memrange_absolute)
9005796c8dcSSimon Schubert     {
9015796c8dcSSimon Schubert       if ((bfd_vma) a->start < (bfd_vma) b->start)
9025796c8dcSSimon Schubert 	return -1;
9035796c8dcSSimon Schubert       if ((bfd_vma) a->start > (bfd_vma) b->start)
9045796c8dcSSimon Schubert 	return 1;
9055796c8dcSSimon Schubert     }
9065796c8dcSSimon Schubert   else
9075796c8dcSSimon Schubert     {
9085796c8dcSSimon Schubert       if (a->start < b->start)
9095796c8dcSSimon Schubert 	return -1;
9105796c8dcSSimon Schubert       if (a->start > b->start)
9115796c8dcSSimon Schubert 	return 1;
9125796c8dcSSimon Schubert     }
9135796c8dcSSimon Schubert   return 0;
9145796c8dcSSimon Schubert }
9155796c8dcSSimon Schubert 
9165796c8dcSSimon Schubert /* Sort the memrange list using qsort, and merge adjacent memranges.  */
9175796c8dcSSimon Schubert static void
memrange_sortmerge(struct collection_list * memranges)9185796c8dcSSimon Schubert memrange_sortmerge (struct collection_list *memranges)
9195796c8dcSSimon Schubert {
9205796c8dcSSimon Schubert   int a, b;
9215796c8dcSSimon Schubert 
9225796c8dcSSimon Schubert   qsort (memranges->list, memranges->next_memrange,
9235796c8dcSSimon Schubert 	 sizeof (struct memrange), memrange_cmp);
9245796c8dcSSimon Schubert   if (memranges->next_memrange > 0)
9255796c8dcSSimon Schubert     {
9265796c8dcSSimon Schubert       for (a = 0, b = 1; b < memranges->next_memrange; b++)
9275796c8dcSSimon Schubert 	{
928c50c785cSJohn Marino 	  /* If memrange b overlaps or is adjacent to memrange a,
929c50c785cSJohn Marino 	     merge them.  */
930c50c785cSJohn Marino 	  if (memranges->list[a].type == memranges->list[b].type
931c50c785cSJohn Marino 	      && memranges->list[b].start <= memranges->list[a].end)
9325796c8dcSSimon Schubert 	    {
9335796c8dcSSimon Schubert 	      if (memranges->list[b].end > memranges->list[a].end)
9345796c8dcSSimon Schubert 		memranges->list[a].end = memranges->list[b].end;
9355796c8dcSSimon Schubert 	      continue;		/* next b, same a */
9365796c8dcSSimon Schubert 	    }
9375796c8dcSSimon Schubert 	  a++;			/* next a */
9385796c8dcSSimon Schubert 	  if (a != b)
9395796c8dcSSimon Schubert 	    memcpy (&memranges->list[a], &memranges->list[b],
9405796c8dcSSimon Schubert 		    sizeof (struct memrange));
9415796c8dcSSimon Schubert 	}
9425796c8dcSSimon Schubert       memranges->next_memrange = a + 1;
9435796c8dcSSimon Schubert     }
9445796c8dcSSimon Schubert }
9455796c8dcSSimon Schubert 
9465796c8dcSSimon Schubert /* Add a register to a collection list.  */
9475796c8dcSSimon Schubert static void
add_register(struct collection_list * collection,unsigned int regno)9485796c8dcSSimon Schubert add_register (struct collection_list *collection, unsigned int regno)
9495796c8dcSSimon Schubert {
9505796c8dcSSimon Schubert   if (info_verbose)
9515796c8dcSSimon Schubert     printf_filtered ("collect register %d\n", regno);
9525796c8dcSSimon Schubert   if (regno >= (8 * sizeof (collection->regs_mask)))
9535796c8dcSSimon Schubert     error (_("Internal: register number %d too large for tracepoint"),
9545796c8dcSSimon Schubert 	   regno);
9555796c8dcSSimon Schubert   collection->regs_mask[regno / 8] |= 1 << (regno % 8);
9565796c8dcSSimon Schubert }
9575796c8dcSSimon Schubert 
958c50c785cSJohn Marino /* Add a memrange to a collection list.  */
9595796c8dcSSimon Schubert static void
add_memrange(struct collection_list * memranges,int type,bfd_signed_vma base,unsigned long len)9605796c8dcSSimon Schubert add_memrange (struct collection_list *memranges,
9615796c8dcSSimon Schubert 	      int type, bfd_signed_vma base,
9625796c8dcSSimon Schubert 	      unsigned long len)
9635796c8dcSSimon Schubert {
9645796c8dcSSimon Schubert   if (info_verbose)
9655796c8dcSSimon Schubert     {
9665796c8dcSSimon Schubert       printf_filtered ("(%d,", type);
9675796c8dcSSimon Schubert       printf_vma (base);
9685796c8dcSSimon Schubert       printf_filtered (",%ld)\n", len);
9695796c8dcSSimon Schubert     }
9705796c8dcSSimon Schubert 
9715796c8dcSSimon Schubert   /* type: memrange_absolute == memory, other n == basereg */
9725796c8dcSSimon Schubert   memranges->list[memranges->next_memrange].type = type;
9735796c8dcSSimon Schubert   /* base: addr if memory, offset if reg relative.  */
9745796c8dcSSimon Schubert   memranges->list[memranges->next_memrange].start = base;
9755796c8dcSSimon Schubert   /* len: we actually save end (base + len) for convenience */
9765796c8dcSSimon Schubert   memranges->list[memranges->next_memrange].end = base + len;
9775796c8dcSSimon Schubert   memranges->next_memrange++;
9785796c8dcSSimon Schubert   if (memranges->next_memrange >= memranges->listsize)
9795796c8dcSSimon Schubert     {
9805796c8dcSSimon Schubert       memranges->listsize *= 2;
9815796c8dcSSimon Schubert       memranges->list = xrealloc (memranges->list,
9825796c8dcSSimon Schubert 				  memranges->listsize);
9835796c8dcSSimon Schubert     }
9845796c8dcSSimon Schubert 
9855796c8dcSSimon Schubert   if (type != memrange_absolute)    /* Better collect the base register!  */
9865796c8dcSSimon Schubert     add_register (memranges, type);
9875796c8dcSSimon Schubert }
9885796c8dcSSimon Schubert 
9895796c8dcSSimon Schubert /* Add a symbol to a collection list.  */
9905796c8dcSSimon Schubert static void
collect_symbol(struct collection_list * collect,struct symbol * sym,struct gdbarch * gdbarch,long frame_regno,long frame_offset,CORE_ADDR scope)9915796c8dcSSimon Schubert collect_symbol (struct collection_list *collect,
9925796c8dcSSimon Schubert 		struct symbol *sym,
9935796c8dcSSimon Schubert 		struct gdbarch *gdbarch,
994cf7f2e2dSJohn Marino 		long frame_regno, long frame_offset,
995cf7f2e2dSJohn Marino 		CORE_ADDR scope)
9965796c8dcSSimon Schubert {
9975796c8dcSSimon Schubert   unsigned long len;
9985796c8dcSSimon Schubert   unsigned int reg;
9995796c8dcSSimon Schubert   bfd_signed_vma offset;
1000cf7f2e2dSJohn Marino   int treat_as_expr = 0;
10015796c8dcSSimon Schubert 
10025796c8dcSSimon Schubert   len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
10035796c8dcSSimon Schubert   switch (SYMBOL_CLASS (sym))
10045796c8dcSSimon Schubert     {
10055796c8dcSSimon Schubert     default:
10065796c8dcSSimon Schubert       printf_filtered ("%s: don't know symbol class %d\n",
10075796c8dcSSimon Schubert 		       SYMBOL_PRINT_NAME (sym),
10085796c8dcSSimon Schubert 		       SYMBOL_CLASS (sym));
10095796c8dcSSimon Schubert       break;
10105796c8dcSSimon Schubert     case LOC_CONST:
1011*ef5ccd6cSJohn Marino       printf_filtered ("constant %s (value %s) will not be collected.\n",
1012*ef5ccd6cSJohn Marino 		       SYMBOL_PRINT_NAME (sym), plongest (SYMBOL_VALUE (sym)));
10135796c8dcSSimon Schubert       break;
10145796c8dcSSimon Schubert     case LOC_STATIC:
10155796c8dcSSimon Schubert       offset = SYMBOL_VALUE_ADDRESS (sym);
10165796c8dcSSimon Schubert       if (info_verbose)
10175796c8dcSSimon Schubert 	{
10185796c8dcSSimon Schubert 	  char tmp[40];
10195796c8dcSSimon Schubert 
10205796c8dcSSimon Schubert 	  sprintf_vma (tmp, offset);
10215796c8dcSSimon Schubert 	  printf_filtered ("LOC_STATIC %s: collect %ld bytes at %s.\n",
10225796c8dcSSimon Schubert 			   SYMBOL_PRINT_NAME (sym), len,
10235796c8dcSSimon Schubert 			   tmp /* address */);
10245796c8dcSSimon Schubert 	}
1025cf7f2e2dSJohn Marino       /* A struct may be a C++ class with static fields, go to general
1026cf7f2e2dSJohn Marino 	 expression handling.  */
1027cf7f2e2dSJohn Marino       if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT)
1028cf7f2e2dSJohn Marino 	treat_as_expr = 1;
1029cf7f2e2dSJohn Marino       else
10305796c8dcSSimon Schubert 	add_memrange (collect, memrange_absolute, offset, len);
10315796c8dcSSimon Schubert       break;
10325796c8dcSSimon Schubert     case LOC_REGISTER:
10335796c8dcSSimon Schubert       reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch);
10345796c8dcSSimon Schubert       if (info_verbose)
10355796c8dcSSimon Schubert 	printf_filtered ("LOC_REG[parm] %s: ",
10365796c8dcSSimon Schubert 			 SYMBOL_PRINT_NAME (sym));
10375796c8dcSSimon Schubert       add_register (collect, reg);
10385796c8dcSSimon Schubert       /* Check for doubles stored in two registers.  */
10395796c8dcSSimon Schubert       /* FIXME: how about larger types stored in 3 or more regs?  */
10405796c8dcSSimon Schubert       if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
10415796c8dcSSimon Schubert 	  len > register_size (gdbarch, reg))
10425796c8dcSSimon Schubert 	add_register (collect, reg + 1);
10435796c8dcSSimon Schubert       break;
10445796c8dcSSimon Schubert     case LOC_REF_ARG:
10455796c8dcSSimon Schubert       printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
10465796c8dcSSimon Schubert       printf_filtered ("       (will not collect %s)\n",
10475796c8dcSSimon Schubert 		       SYMBOL_PRINT_NAME (sym));
10485796c8dcSSimon Schubert       break;
10495796c8dcSSimon Schubert     case LOC_ARG:
10505796c8dcSSimon Schubert       reg = frame_regno;
10515796c8dcSSimon Schubert       offset = frame_offset + SYMBOL_VALUE (sym);
10525796c8dcSSimon Schubert       if (info_verbose)
10535796c8dcSSimon Schubert 	{
10545796c8dcSSimon Schubert 	  printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ",
10555796c8dcSSimon Schubert 			   SYMBOL_PRINT_NAME (sym), len);
10565796c8dcSSimon Schubert 	  printf_vma (offset);
10575796c8dcSSimon Schubert 	  printf_filtered (" from frame ptr reg %d\n", reg);
10585796c8dcSSimon Schubert 	}
10595796c8dcSSimon Schubert       add_memrange (collect, reg, offset, len);
10605796c8dcSSimon Schubert       break;
10615796c8dcSSimon Schubert     case LOC_REGPARM_ADDR:
10625796c8dcSSimon Schubert       reg = SYMBOL_VALUE (sym);
10635796c8dcSSimon Schubert       offset = 0;
10645796c8dcSSimon Schubert       if (info_verbose)
10655796c8dcSSimon Schubert 	{
10665796c8dcSSimon Schubert 	  printf_filtered ("LOC_REGPARM_ADDR %s: Collect %ld bytes at offset ",
10675796c8dcSSimon Schubert 			   SYMBOL_PRINT_NAME (sym), len);
10685796c8dcSSimon Schubert 	  printf_vma (offset);
10695796c8dcSSimon Schubert 	  printf_filtered (" from reg %d\n", reg);
10705796c8dcSSimon Schubert 	}
10715796c8dcSSimon Schubert       add_memrange (collect, reg, offset, len);
10725796c8dcSSimon Schubert       break;
10735796c8dcSSimon Schubert     case LOC_LOCAL:
10745796c8dcSSimon Schubert       reg = frame_regno;
10755796c8dcSSimon Schubert       offset = frame_offset + SYMBOL_VALUE (sym);
10765796c8dcSSimon Schubert       if (info_verbose)
10775796c8dcSSimon Schubert 	{
10785796c8dcSSimon Schubert 	  printf_filtered ("LOC_LOCAL %s: Collect %ld bytes at offset ",
10795796c8dcSSimon Schubert 			   SYMBOL_PRINT_NAME (sym), len);
10805796c8dcSSimon Schubert 	  printf_vma (offset);
10815796c8dcSSimon Schubert 	  printf_filtered (" from frame ptr reg %d\n", reg);
10825796c8dcSSimon Schubert 	}
10835796c8dcSSimon Schubert       add_memrange (collect, reg, offset, len);
10845796c8dcSSimon Schubert       break;
1085cf7f2e2dSJohn Marino 
10865796c8dcSSimon Schubert     case LOC_UNRESOLVED:
1087cf7f2e2dSJohn Marino       treat_as_expr = 1;
10885796c8dcSSimon Schubert       break;
1089cf7f2e2dSJohn Marino 
10905796c8dcSSimon Schubert     case LOC_OPTIMIZED_OUT:
10915796c8dcSSimon Schubert       printf_filtered ("%s has been optimized out of existence.\n",
10925796c8dcSSimon Schubert 		       SYMBOL_PRINT_NAME (sym));
10935796c8dcSSimon Schubert       break;
1094cf7f2e2dSJohn Marino 
1095cf7f2e2dSJohn Marino     case LOC_COMPUTED:
1096cf7f2e2dSJohn Marino       treat_as_expr = 1;
1097cf7f2e2dSJohn Marino       break;
10985796c8dcSSimon Schubert     }
1099cf7f2e2dSJohn Marino 
1100cf7f2e2dSJohn Marino   /* Expressions are the most general case.  */
1101cf7f2e2dSJohn Marino   if (treat_as_expr)
1102cf7f2e2dSJohn Marino     {
1103cf7f2e2dSJohn Marino       struct agent_expr *aexpr;
1104cf7f2e2dSJohn Marino       struct cleanup *old_chain1 = NULL;
1105cf7f2e2dSJohn Marino 
1106cf7f2e2dSJohn Marino       aexpr = gen_trace_for_var (scope, gdbarch, sym);
1107cf7f2e2dSJohn Marino 
1108cf7f2e2dSJohn Marino       /* It can happen that the symbol is recorded as a computed
1109cf7f2e2dSJohn Marino 	 location, but it's been optimized away and doesn't actually
1110cf7f2e2dSJohn Marino 	 have a location expression.  */
1111cf7f2e2dSJohn Marino       if (!aexpr)
1112cf7f2e2dSJohn Marino 	{
1113cf7f2e2dSJohn Marino 	  printf_filtered ("%s has been optimized out of existence.\n",
1114cf7f2e2dSJohn Marino 			   SYMBOL_PRINT_NAME (sym));
1115cf7f2e2dSJohn Marino 	  return;
1116cf7f2e2dSJohn Marino 	}
1117cf7f2e2dSJohn Marino 
1118cf7f2e2dSJohn Marino       old_chain1 = make_cleanup_free_agent_expr (aexpr);
1119cf7f2e2dSJohn Marino 
1120cf7f2e2dSJohn Marino       ax_reqs (aexpr);
1121cf7f2e2dSJohn Marino 
1122cf7f2e2dSJohn Marino       report_agent_reqs_errors (aexpr);
1123cf7f2e2dSJohn Marino 
1124cf7f2e2dSJohn Marino       discard_cleanups (old_chain1);
1125cf7f2e2dSJohn Marino       add_aexpr (collect, aexpr);
1126cf7f2e2dSJohn Marino 
1127c50c785cSJohn Marino       /* Take care of the registers.  */
1128cf7f2e2dSJohn Marino       if (aexpr->reg_mask_len > 0)
1129cf7f2e2dSJohn Marino 	{
1130cf7f2e2dSJohn Marino 	  int ndx1, ndx2;
1131cf7f2e2dSJohn Marino 
1132cf7f2e2dSJohn Marino 	  for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
1133cf7f2e2dSJohn Marino 	    {
1134c50c785cSJohn Marino 	      QUIT;	/* Allow user to bail out with ^C.  */
1135cf7f2e2dSJohn Marino 	      if (aexpr->reg_mask[ndx1] != 0)
1136cf7f2e2dSJohn Marino 		{
1137c50c785cSJohn Marino 		  /* Assume chars have 8 bits.  */
1138cf7f2e2dSJohn Marino 		  for (ndx2 = 0; ndx2 < 8; ndx2++)
1139cf7f2e2dSJohn Marino 		    if (aexpr->reg_mask[ndx1] & (1 << ndx2))
1140c50c785cSJohn Marino 		      /* It's used -- record it.  */
1141cf7f2e2dSJohn Marino 		      add_register (collect, ndx1 * 8 + ndx2);
1142cf7f2e2dSJohn Marino 		}
1143cf7f2e2dSJohn Marino 	    }
1144cf7f2e2dSJohn Marino 	}
1145cf7f2e2dSJohn Marino     }
1146cf7f2e2dSJohn Marino }
1147cf7f2e2dSJohn Marino 
1148cf7f2e2dSJohn Marino /* Data to be passed around in the calls to the locals and args
1149cf7f2e2dSJohn Marino    iterators.  */
1150cf7f2e2dSJohn Marino 
1151cf7f2e2dSJohn Marino struct add_local_symbols_data
1152cf7f2e2dSJohn Marino {
1153cf7f2e2dSJohn Marino   struct collection_list *collect;
1154cf7f2e2dSJohn Marino   struct gdbarch *gdbarch;
1155cf7f2e2dSJohn Marino   CORE_ADDR pc;
1156cf7f2e2dSJohn Marino   long frame_regno;
1157cf7f2e2dSJohn Marino   long frame_offset;
1158cf7f2e2dSJohn Marino   int count;
1159cf7f2e2dSJohn Marino };
1160cf7f2e2dSJohn Marino 
1161c50c785cSJohn Marino /* The callback for the locals and args iterators.  */
1162cf7f2e2dSJohn Marino 
1163cf7f2e2dSJohn Marino static void
do_collect_symbol(const char * print_name,struct symbol * sym,void * cb_data)1164cf7f2e2dSJohn Marino do_collect_symbol (const char *print_name,
1165cf7f2e2dSJohn Marino 		   struct symbol *sym,
1166cf7f2e2dSJohn Marino 		   void *cb_data)
1167cf7f2e2dSJohn Marino {
1168cf7f2e2dSJohn Marino   struct add_local_symbols_data *p = cb_data;
1169cf7f2e2dSJohn Marino 
1170cf7f2e2dSJohn Marino   collect_symbol (p->collect, sym, p->gdbarch, p->frame_regno,
1171cf7f2e2dSJohn Marino 		  p->frame_offset, p->pc);
1172cf7f2e2dSJohn Marino   p->count++;
11735796c8dcSSimon Schubert }
11745796c8dcSSimon Schubert 
1175c50c785cSJohn Marino /* Add all locals (or args) symbols to collection list.  */
11765796c8dcSSimon Schubert static void
add_local_symbols(struct collection_list * collect,struct gdbarch * gdbarch,CORE_ADDR pc,long frame_regno,long frame_offset,int type)11775796c8dcSSimon Schubert add_local_symbols (struct collection_list *collect,
11785796c8dcSSimon Schubert 		   struct gdbarch *gdbarch, CORE_ADDR pc,
11795796c8dcSSimon Schubert 		   long frame_regno, long frame_offset, int type)
11805796c8dcSSimon Schubert {
11815796c8dcSSimon Schubert   struct block *block;
1182cf7f2e2dSJohn Marino   struct add_local_symbols_data cb_data;
11835796c8dcSSimon Schubert 
1184cf7f2e2dSJohn Marino   cb_data.collect = collect;
1185cf7f2e2dSJohn Marino   cb_data.gdbarch = gdbarch;
1186cf7f2e2dSJohn Marino   cb_data.pc = pc;
1187cf7f2e2dSJohn Marino   cb_data.frame_regno = frame_regno;
1188cf7f2e2dSJohn Marino   cb_data.frame_offset = frame_offset;
1189cf7f2e2dSJohn Marino   cb_data.count = 0;
1190cf7f2e2dSJohn Marino 
1191cf7f2e2dSJohn Marino   if (type == 'L')
1192cf7f2e2dSJohn Marino     {
11935796c8dcSSimon Schubert       block = block_for_pc (pc);
1194cf7f2e2dSJohn Marino       if (block == NULL)
11955796c8dcSSimon Schubert 	{
1196cf7f2e2dSJohn Marino 	  warning (_("Can't collect locals; "
1197cf7f2e2dSJohn Marino 		     "no symbol table info available.\n"));
1198cf7f2e2dSJohn Marino 	  return;
11995796c8dcSSimon Schubert 	}
1200cf7f2e2dSJohn Marino 
1201cf7f2e2dSJohn Marino       iterate_over_block_local_vars (block, do_collect_symbol, &cb_data);
1202cf7f2e2dSJohn Marino       if (cb_data.count == 0)
1203cf7f2e2dSJohn Marino 	warning (_("No locals found in scope."));
12045796c8dcSSimon Schubert     }
12055796c8dcSSimon Schubert   else
1206cf7f2e2dSJohn Marino     {
1207cf7f2e2dSJohn Marino       pc = get_pc_function_start (pc);
1208cf7f2e2dSJohn Marino       block = block_for_pc (pc);
1209cf7f2e2dSJohn Marino       if (block == NULL)
1210cf7f2e2dSJohn Marino 	{
1211c50c785cSJohn Marino 	  warning (_("Can't collect args; no symbol table info available."));
1212cf7f2e2dSJohn Marino 	  return;
12135796c8dcSSimon Schubert 	}
1214cf7f2e2dSJohn Marino 
1215cf7f2e2dSJohn Marino       iterate_over_block_arg_vars (block, do_collect_symbol, &cb_data);
1216cf7f2e2dSJohn Marino       if (cb_data.count == 0)
1217cf7f2e2dSJohn Marino 	warning (_("No args found in scope."));
1218cf7f2e2dSJohn Marino     }
1219cf7f2e2dSJohn Marino }
1220cf7f2e2dSJohn Marino 
1221cf7f2e2dSJohn Marino static void
add_static_trace_data(struct collection_list * collection)1222cf7f2e2dSJohn Marino add_static_trace_data (struct collection_list *collection)
1223cf7f2e2dSJohn Marino {
1224cf7f2e2dSJohn Marino   if (info_verbose)
1225cf7f2e2dSJohn Marino     printf_filtered ("collect static trace data\n");
1226cf7f2e2dSJohn Marino   collection->strace_data = 1;
12275796c8dcSSimon Schubert }
12285796c8dcSSimon Schubert 
12295796c8dcSSimon Schubert /* worker function */
12305796c8dcSSimon Schubert static void
clear_collection_list(struct collection_list * list)12315796c8dcSSimon Schubert clear_collection_list (struct collection_list *list)
12325796c8dcSSimon Schubert {
12335796c8dcSSimon Schubert   int ndx;
12345796c8dcSSimon Schubert 
12355796c8dcSSimon Schubert   list->next_memrange = 0;
12365796c8dcSSimon Schubert   for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
12375796c8dcSSimon Schubert     {
12385796c8dcSSimon Schubert       free_agent_expr (list->aexpr_list[ndx]);
12395796c8dcSSimon Schubert       list->aexpr_list[ndx] = NULL;
12405796c8dcSSimon Schubert     }
12415796c8dcSSimon Schubert   list->next_aexpr_elt = 0;
12425796c8dcSSimon Schubert   memset (list->regs_mask, 0, sizeof (list->regs_mask));
1243cf7f2e2dSJohn Marino   list->strace_data = 0;
12445796c8dcSSimon Schubert }
12455796c8dcSSimon Schubert 
1246c50c785cSJohn Marino /* Reduce a collection list to string form (for gdb protocol).  */
12475796c8dcSSimon Schubert static char **
stringify_collection_list(struct collection_list * list,char * string)12485796c8dcSSimon Schubert stringify_collection_list (struct collection_list *list, char *string)
12495796c8dcSSimon Schubert {
12505796c8dcSSimon Schubert   char temp_buf[2048];
12515796c8dcSSimon Schubert   char tmp2[40];
12525796c8dcSSimon Schubert   int count;
12535796c8dcSSimon Schubert   int ndx = 0;
12545796c8dcSSimon Schubert   char *(*str_list)[];
12555796c8dcSSimon Schubert   char *end;
12565796c8dcSSimon Schubert   long i;
12575796c8dcSSimon Schubert 
1258cf7f2e2dSJohn Marino   count = 1 + 1 + list->next_memrange + list->next_aexpr_elt + 1;
12595796c8dcSSimon Schubert   str_list = (char *(*)[]) xmalloc (count * sizeof (char *));
12605796c8dcSSimon Schubert 
1261cf7f2e2dSJohn Marino   if (list->strace_data)
1262cf7f2e2dSJohn Marino     {
1263cf7f2e2dSJohn Marino       if (info_verbose)
1264cf7f2e2dSJohn Marino 	printf_filtered ("\nCollecting static trace data\n");
1265cf7f2e2dSJohn Marino       end = temp_buf;
1266cf7f2e2dSJohn Marino       *end++ = 'L';
1267cf7f2e2dSJohn Marino       (*str_list)[ndx] = savestring (temp_buf, end - temp_buf);
1268cf7f2e2dSJohn Marino       ndx++;
1269cf7f2e2dSJohn Marino     }
1270cf7f2e2dSJohn Marino 
12715796c8dcSSimon Schubert   for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1272c50c785cSJohn Marino     if (list->regs_mask[i] != 0)    /* Skip leading zeroes in regs_mask.  */
12735796c8dcSSimon Schubert       break;
1274c50c785cSJohn Marino   if (list->regs_mask[i] != 0)	/* Prepare to send regs_mask to the stub.  */
12755796c8dcSSimon Schubert     {
12765796c8dcSSimon Schubert       if (info_verbose)
12775796c8dcSSimon Schubert 	printf_filtered ("\nCollecting registers (mask): 0x");
12785796c8dcSSimon Schubert       end = temp_buf;
12795796c8dcSSimon Schubert       *end++ = 'R';
12805796c8dcSSimon Schubert       for (; i >= 0; i--)
12815796c8dcSSimon Schubert 	{
1282c50c785cSJohn Marino 	  QUIT;			/* Allow user to bail out with ^C.  */
12835796c8dcSSimon Schubert 	  if (info_verbose)
12845796c8dcSSimon Schubert 	    printf_filtered ("%02X", list->regs_mask[i]);
12855796c8dcSSimon Schubert 	  sprintf (end, "%02X", list->regs_mask[i]);
12865796c8dcSSimon Schubert 	  end += 2;
12875796c8dcSSimon Schubert 	}
12885796c8dcSSimon Schubert       (*str_list)[ndx] = xstrdup (temp_buf);
12895796c8dcSSimon Schubert       ndx++;
12905796c8dcSSimon Schubert     }
12915796c8dcSSimon Schubert   if (info_verbose)
12925796c8dcSSimon Schubert     printf_filtered ("\n");
12935796c8dcSSimon Schubert   if (list->next_memrange > 0 && info_verbose)
12945796c8dcSSimon Schubert     printf_filtered ("Collecting memranges: \n");
12955796c8dcSSimon Schubert   for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
12965796c8dcSSimon Schubert     {
1297c50c785cSJohn Marino       QUIT;			/* Allow user to bail out with ^C.  */
12985796c8dcSSimon Schubert       sprintf_vma (tmp2, list->list[i].start);
12995796c8dcSSimon Schubert       if (info_verbose)
13005796c8dcSSimon Schubert 	{
13015796c8dcSSimon Schubert 	  printf_filtered ("(%d, %s, %ld)\n",
13025796c8dcSSimon Schubert 			   list->list[i].type,
13035796c8dcSSimon Schubert 			   tmp2,
13045796c8dcSSimon Schubert 			   (long) (list->list[i].end - list->list[i].start));
13055796c8dcSSimon Schubert 	}
13065796c8dcSSimon Schubert       if (count + 27 > MAX_AGENT_EXPR_LEN)
13075796c8dcSSimon Schubert 	{
13085796c8dcSSimon Schubert 	  (*str_list)[ndx] = savestring (temp_buf, count);
13095796c8dcSSimon Schubert 	  ndx++;
13105796c8dcSSimon Schubert 	  count = 0;
13115796c8dcSSimon Schubert 	  end = temp_buf;
13125796c8dcSSimon Schubert 	}
13135796c8dcSSimon Schubert 
13145796c8dcSSimon Schubert       {
13155796c8dcSSimon Schubert         bfd_signed_vma length = list->list[i].end - list->list[i].start;
13165796c8dcSSimon Schubert 
13175796c8dcSSimon Schubert         /* The "%X" conversion specifier expects an unsigned argument,
13185796c8dcSSimon Schubert            so passing -1 (memrange_absolute) to it directly gives you
13195796c8dcSSimon Schubert            "FFFFFFFF" (or more, depending on sizeof (unsigned)).
13205796c8dcSSimon Schubert            Special-case it.  */
13215796c8dcSSimon Schubert         if (list->list[i].type == memrange_absolute)
13225796c8dcSSimon Schubert           sprintf (end, "M-1,%s,%lX", tmp2, (long) length);
13235796c8dcSSimon Schubert         else
13245796c8dcSSimon Schubert           sprintf (end, "M%X,%s,%lX", list->list[i].type, tmp2, (long) length);
13255796c8dcSSimon Schubert       }
13265796c8dcSSimon Schubert 
13275796c8dcSSimon Schubert       count += strlen (end);
13285796c8dcSSimon Schubert       end = temp_buf + count;
13295796c8dcSSimon Schubert     }
13305796c8dcSSimon Schubert 
13315796c8dcSSimon Schubert   for (i = 0; i < list->next_aexpr_elt; i++)
13325796c8dcSSimon Schubert     {
1333c50c785cSJohn Marino       QUIT;			/* Allow user to bail out with ^C.  */
13345796c8dcSSimon Schubert       if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
13355796c8dcSSimon Schubert 	{
13365796c8dcSSimon Schubert 	  (*str_list)[ndx] = savestring (temp_buf, count);
13375796c8dcSSimon Schubert 	  ndx++;
13385796c8dcSSimon Schubert 	  count = 0;
13395796c8dcSSimon Schubert 	  end = temp_buf;
13405796c8dcSSimon Schubert 	}
13415796c8dcSSimon Schubert       sprintf (end, "X%08X,", list->aexpr_list[i]->len);
13425796c8dcSSimon Schubert       end += 10;		/* 'X' + 8 hex digits + ',' */
13435796c8dcSSimon Schubert       count += 10;
13445796c8dcSSimon Schubert 
13455796c8dcSSimon Schubert       end = mem2hex (list->aexpr_list[i]->buf,
13465796c8dcSSimon Schubert 		     end, list->aexpr_list[i]->len);
13475796c8dcSSimon Schubert       count += 2 * list->aexpr_list[i]->len;
13485796c8dcSSimon Schubert     }
13495796c8dcSSimon Schubert 
13505796c8dcSSimon Schubert   if (count != 0)
13515796c8dcSSimon Schubert     {
13525796c8dcSSimon Schubert       (*str_list)[ndx] = savestring (temp_buf, count);
13535796c8dcSSimon Schubert       ndx++;
13545796c8dcSSimon Schubert       count = 0;
13555796c8dcSSimon Schubert       end = temp_buf;
13565796c8dcSSimon Schubert     }
13575796c8dcSSimon Schubert   (*str_list)[ndx] = NULL;
13585796c8dcSSimon Schubert 
13595796c8dcSSimon Schubert   if (ndx == 0)
13605796c8dcSSimon Schubert     {
13615796c8dcSSimon Schubert       xfree (str_list);
13625796c8dcSSimon Schubert       return NULL;
13635796c8dcSSimon Schubert     }
13645796c8dcSSimon Schubert   else
13655796c8dcSSimon Schubert     return *str_list;
13665796c8dcSSimon Schubert }
13675796c8dcSSimon Schubert 
13685796c8dcSSimon Schubert 
13695796c8dcSSimon Schubert static void
encode_actions_1(struct command_line * action,struct breakpoint * t,struct bp_location * tloc,int frame_reg,LONGEST frame_offset,struct collection_list * collect,struct collection_list * stepping_list)1370cf7f2e2dSJohn Marino encode_actions_1 (struct command_line *action,
1371cf7f2e2dSJohn Marino 		  struct breakpoint *t,
1372cf7f2e2dSJohn Marino 		  struct bp_location *tloc,
1373cf7f2e2dSJohn Marino 		  int frame_reg,
1374cf7f2e2dSJohn Marino 		  LONGEST frame_offset,
1375cf7f2e2dSJohn Marino 		  struct collection_list *collect,
1376cf7f2e2dSJohn Marino 		  struct collection_list *stepping_list)
13775796c8dcSSimon Schubert {
13785796c8dcSSimon Schubert   char *action_exp;
13795796c8dcSSimon Schubert   struct expression *exp = NULL;
13805796c8dcSSimon Schubert   int i;
13815796c8dcSSimon Schubert   struct value *tempval;
13825796c8dcSSimon Schubert   struct cmd_list_element *cmd;
13835796c8dcSSimon Schubert   struct agent_expr *aexpr;
13845796c8dcSSimon Schubert 
1385cf7f2e2dSJohn Marino   for (; action; action = action->next)
13865796c8dcSSimon Schubert     {
1387c50c785cSJohn Marino       QUIT;			/* Allow user to bail out with ^C.  */
1388cf7f2e2dSJohn Marino       action_exp = action->line;
1389*ef5ccd6cSJohn Marino       action_exp = skip_spaces (action_exp);
13905796c8dcSSimon Schubert 
13915796c8dcSSimon Schubert       cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
13925796c8dcSSimon Schubert       if (cmd == 0)
13935796c8dcSSimon Schubert 	error (_("Bad action list item: %s"), action_exp);
13945796c8dcSSimon Schubert 
13955796c8dcSSimon Schubert       if (cmd_cfunc_eq (cmd, collect_pseudocommand))
13965796c8dcSSimon Schubert 	{
1397a45ae5f8SJohn Marino 	  trace_string_kludge = 0;
1398a45ae5f8SJohn Marino 	  if (*action_exp == '/')
1399a45ae5f8SJohn Marino 	    action_exp = decode_agent_options (action_exp);
1400a45ae5f8SJohn Marino 
14015796c8dcSSimon Schubert 	  do
1402c50c785cSJohn Marino 	    {			/* Repeat over a comma-separated list.  */
1403c50c785cSJohn Marino 	      QUIT;		/* Allow user to bail out with ^C.  */
1404*ef5ccd6cSJohn Marino 	      action_exp = skip_spaces (action_exp);
14055796c8dcSSimon Schubert 
14065796c8dcSSimon Schubert 	      if (0 == strncasecmp ("$reg", action_exp, 4))
14075796c8dcSSimon Schubert 		{
1408a45ae5f8SJohn Marino 		  for (i = 0; i < gdbarch_num_regs (tloc->gdbarch); i++)
14095796c8dcSSimon Schubert 		    add_register (collect, i);
14105796c8dcSSimon Schubert 		  action_exp = strchr (action_exp, ',');	/* more? */
14115796c8dcSSimon Schubert 		}
14125796c8dcSSimon Schubert 	      else if (0 == strncasecmp ("$arg", action_exp, 4))
14135796c8dcSSimon Schubert 		{
14145796c8dcSSimon Schubert 		  add_local_symbols (collect,
1415a45ae5f8SJohn Marino 				     tloc->gdbarch,
1416cf7f2e2dSJohn Marino 				     tloc->address,
14175796c8dcSSimon Schubert 				     frame_reg,
14185796c8dcSSimon Schubert 				     frame_offset,
14195796c8dcSSimon Schubert 				     'A');
14205796c8dcSSimon Schubert 		  action_exp = strchr (action_exp, ',');	/* more? */
14215796c8dcSSimon Schubert 		}
14225796c8dcSSimon Schubert 	      else if (0 == strncasecmp ("$loc", action_exp, 4))
14235796c8dcSSimon Schubert 		{
14245796c8dcSSimon Schubert 		  add_local_symbols (collect,
1425a45ae5f8SJohn Marino 				     tloc->gdbarch,
1426cf7f2e2dSJohn Marino 				     tloc->address,
14275796c8dcSSimon Schubert 				     frame_reg,
14285796c8dcSSimon Schubert 				     frame_offset,
14295796c8dcSSimon Schubert 				     'L');
14305796c8dcSSimon Schubert 		  action_exp = strchr (action_exp, ',');	/* more? */
14315796c8dcSSimon Schubert 		}
1432a45ae5f8SJohn Marino 	      else if (0 == strncasecmp ("$_ret", action_exp, 5))
1433a45ae5f8SJohn Marino 		{
1434a45ae5f8SJohn Marino 		  struct cleanup *old_chain1 = NULL;
1435a45ae5f8SJohn Marino 
1436a45ae5f8SJohn Marino 		  aexpr = gen_trace_for_return_address (tloc->address,
1437a45ae5f8SJohn Marino 							tloc->gdbarch);
1438a45ae5f8SJohn Marino 
1439a45ae5f8SJohn Marino 		  old_chain1 = make_cleanup_free_agent_expr (aexpr);
1440a45ae5f8SJohn Marino 
1441a45ae5f8SJohn Marino 		  ax_reqs (aexpr);
1442a45ae5f8SJohn Marino 		  report_agent_reqs_errors (aexpr);
1443a45ae5f8SJohn Marino 
1444a45ae5f8SJohn Marino 		  discard_cleanups (old_chain1);
1445a45ae5f8SJohn Marino 		  add_aexpr (collect, aexpr);
1446a45ae5f8SJohn Marino 
1447a45ae5f8SJohn Marino 		  /* take care of the registers */
1448a45ae5f8SJohn Marino 		  if (aexpr->reg_mask_len > 0)
1449a45ae5f8SJohn Marino 		    {
1450a45ae5f8SJohn Marino 		      int ndx1, ndx2;
1451a45ae5f8SJohn Marino 
1452a45ae5f8SJohn Marino 		      for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
1453a45ae5f8SJohn Marino 			{
1454a45ae5f8SJohn Marino 			  QUIT;	/* allow user to bail out with ^C */
1455a45ae5f8SJohn Marino 			  if (aexpr->reg_mask[ndx1] != 0)
1456a45ae5f8SJohn Marino 			    {
1457a45ae5f8SJohn Marino 			      /* assume chars have 8 bits */
1458a45ae5f8SJohn Marino 			      for (ndx2 = 0; ndx2 < 8; ndx2++)
1459a45ae5f8SJohn Marino 				if (aexpr->reg_mask[ndx1] & (1 << ndx2))
1460a45ae5f8SJohn Marino 				  /* it's used -- record it */
1461a45ae5f8SJohn Marino 				  add_register (collect,
1462a45ae5f8SJohn Marino 						ndx1 * 8 + ndx2);
1463a45ae5f8SJohn Marino 			    }
1464a45ae5f8SJohn Marino 			}
1465a45ae5f8SJohn Marino 		    }
1466a45ae5f8SJohn Marino 
1467a45ae5f8SJohn Marino 		  action_exp = strchr (action_exp, ',');	/* more? */
1468a45ae5f8SJohn Marino 		}
1469cf7f2e2dSJohn Marino 	      else if (0 == strncasecmp ("$_sdata", action_exp, 7))
1470cf7f2e2dSJohn Marino 		{
1471cf7f2e2dSJohn Marino 		  add_static_trace_data (collect);
1472cf7f2e2dSJohn Marino 		  action_exp = strchr (action_exp, ',');	/* more? */
1473cf7f2e2dSJohn Marino 		}
14745796c8dcSSimon Schubert 	      else
14755796c8dcSSimon Schubert 		{
1476*ef5ccd6cSJohn Marino 		  unsigned long addr;
14775796c8dcSSimon Schubert 		  struct cleanup *old_chain = NULL;
14785796c8dcSSimon Schubert 		  struct cleanup *old_chain1 = NULL;
1479*ef5ccd6cSJohn Marino 		  const char *q;
14805796c8dcSSimon Schubert 
1481*ef5ccd6cSJohn Marino 		  q = action_exp;
1482*ef5ccd6cSJohn Marino 		  exp = parse_exp_1 (&q, tloc->address,
1483cf7f2e2dSJohn Marino 				     block_for_pc (tloc->address), 1);
1484*ef5ccd6cSJohn Marino 		  action_exp = (char *) q;
14855796c8dcSSimon Schubert 		  old_chain = make_cleanup (free_current_contents, &exp);
14865796c8dcSSimon Schubert 
14875796c8dcSSimon Schubert 		  switch (exp->elts[0].opcode)
14885796c8dcSSimon Schubert 		    {
14895796c8dcSSimon Schubert 		    case OP_REGISTER:
14905796c8dcSSimon Schubert 		      {
14915796c8dcSSimon Schubert 			const char *name = &exp->elts[2].string;
14925796c8dcSSimon Schubert 
1493a45ae5f8SJohn Marino 			i = user_reg_map_name_to_regnum (tloc->gdbarch,
14945796c8dcSSimon Schubert 							 name, strlen (name));
14955796c8dcSSimon Schubert 			if (i == -1)
14965796c8dcSSimon Schubert 			  internal_error (__FILE__, __LINE__,
14975796c8dcSSimon Schubert 					  _("Register $%s not available"),
14985796c8dcSSimon Schubert 					  name);
14995796c8dcSSimon Schubert 			if (info_verbose)
15005796c8dcSSimon Schubert 			  printf_filtered ("OP_REGISTER: ");
15015796c8dcSSimon Schubert 			add_register (collect, i);
15025796c8dcSSimon Schubert 			break;
15035796c8dcSSimon Schubert 		      }
15045796c8dcSSimon Schubert 
15055796c8dcSSimon Schubert 		    case UNOP_MEMVAL:
1506c50c785cSJohn Marino 		      /* Safe because we know it's a simple expression.  */
15075796c8dcSSimon Schubert 		      tempval = evaluate_expression (exp);
15085796c8dcSSimon Schubert 		      addr = value_address (tempval);
1509*ef5ccd6cSJohn Marino 		      /* Initialize the TYPE_LENGTH if it is a typedef.  */
1510*ef5ccd6cSJohn Marino 		      check_typedef (exp->elts[1].type);
1511*ef5ccd6cSJohn Marino 		      add_memrange (collect, memrange_absolute, addr,
1512*ef5ccd6cSJohn Marino 				    TYPE_LENGTH (exp->elts[1].type));
15135796c8dcSSimon Schubert 		      break;
15145796c8dcSSimon Schubert 
15155796c8dcSSimon Schubert 		    case OP_VAR_VALUE:
15165796c8dcSSimon Schubert 		      collect_symbol (collect,
15175796c8dcSSimon Schubert 				      exp->elts[2].symbol,
1518a45ae5f8SJohn Marino 				      tloc->gdbarch,
15195796c8dcSSimon Schubert 				      frame_reg,
1520cf7f2e2dSJohn Marino 				      frame_offset,
1521cf7f2e2dSJohn Marino 				      tloc->address);
15225796c8dcSSimon Schubert 		      break;
15235796c8dcSSimon Schubert 
1524c50c785cSJohn Marino 		    default:	/* Full-fledged expression.  */
1525cf7f2e2dSJohn Marino 		      aexpr = gen_trace_for_expr (tloc->address, exp);
15265796c8dcSSimon Schubert 
15275796c8dcSSimon Schubert 		      old_chain1 = make_cleanup_free_agent_expr (aexpr);
15285796c8dcSSimon Schubert 
1529cf7f2e2dSJohn Marino 		      ax_reqs (aexpr);
15305796c8dcSSimon Schubert 
1531cf7f2e2dSJohn Marino 		      report_agent_reqs_errors (aexpr);
15325796c8dcSSimon Schubert 
15335796c8dcSSimon Schubert 		      discard_cleanups (old_chain1);
15345796c8dcSSimon Schubert 		      add_aexpr (collect, aexpr);
15355796c8dcSSimon Schubert 
1536c50c785cSJohn Marino 		      /* Take care of the registers.  */
1537cf7f2e2dSJohn Marino 		      if (aexpr->reg_mask_len > 0)
15385796c8dcSSimon Schubert 			{
15395796c8dcSSimon Schubert 			  int ndx1;
15405796c8dcSSimon Schubert 			  int ndx2;
15415796c8dcSSimon Schubert 
1542cf7f2e2dSJohn Marino 			  for (ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
15435796c8dcSSimon Schubert 			    {
1544c50c785cSJohn Marino 			      QUIT;	/* Allow user to bail out with ^C.  */
1545cf7f2e2dSJohn Marino 			      if (aexpr->reg_mask[ndx1] != 0)
15465796c8dcSSimon Schubert 				{
1547c50c785cSJohn Marino 				  /* Assume chars have 8 bits.  */
15485796c8dcSSimon Schubert 				  for (ndx2 = 0; ndx2 < 8; ndx2++)
1549cf7f2e2dSJohn Marino 				    if (aexpr->reg_mask[ndx1] & (1 << ndx2))
1550c50c785cSJohn Marino 				      /* It's used -- record it.  */
15515796c8dcSSimon Schubert 				      add_register (collect,
15525796c8dcSSimon Schubert 						    ndx1 * 8 + ndx2);
15535796c8dcSSimon Schubert 				}
15545796c8dcSSimon Schubert 			    }
15555796c8dcSSimon Schubert 			}
15565796c8dcSSimon Schubert 		      break;
15575796c8dcSSimon Schubert 		    }		/* switch */
15585796c8dcSSimon Schubert 		  do_cleanups (old_chain);
15595796c8dcSSimon Schubert 		}		/* do */
15605796c8dcSSimon Schubert 	    }
15615796c8dcSSimon Schubert 	  while (action_exp && *action_exp++ == ',');
15625796c8dcSSimon Schubert 	}			/* if */
1563cf7f2e2dSJohn Marino       else if (cmd_cfunc_eq (cmd, teval_pseudocommand))
1564cf7f2e2dSJohn Marino 	{
1565cf7f2e2dSJohn Marino 	  do
1566c50c785cSJohn Marino 	    {			/* Repeat over a comma-separated list.  */
1567c50c785cSJohn Marino 	      QUIT;		/* Allow user to bail out with ^C.  */
1568*ef5ccd6cSJohn Marino 	      action_exp = skip_spaces (action_exp);
1569cf7f2e2dSJohn Marino 
1570cf7f2e2dSJohn Marino 		{
1571cf7f2e2dSJohn Marino 		  struct cleanup *old_chain = NULL;
1572cf7f2e2dSJohn Marino 		  struct cleanup *old_chain1 = NULL;
1573*ef5ccd6cSJohn Marino 		  const char *q;
1574cf7f2e2dSJohn Marino 
1575*ef5ccd6cSJohn Marino 		  q = action_exp;
1576*ef5ccd6cSJohn Marino 		  exp = parse_exp_1 (&q, tloc->address,
1577cf7f2e2dSJohn Marino 				     block_for_pc (tloc->address), 1);
1578*ef5ccd6cSJohn Marino 		  action_exp = (char *) q;
1579cf7f2e2dSJohn Marino 		  old_chain = make_cleanup (free_current_contents, &exp);
1580cf7f2e2dSJohn Marino 
1581cf7f2e2dSJohn Marino 		  aexpr = gen_eval_for_expr (tloc->address, exp);
1582cf7f2e2dSJohn Marino 		  old_chain1 = make_cleanup_free_agent_expr (aexpr);
1583cf7f2e2dSJohn Marino 
1584cf7f2e2dSJohn Marino 		  ax_reqs (aexpr);
1585cf7f2e2dSJohn Marino 		  report_agent_reqs_errors (aexpr);
1586cf7f2e2dSJohn Marino 
1587cf7f2e2dSJohn Marino 		  discard_cleanups (old_chain1);
1588cf7f2e2dSJohn Marino 		  /* Even though we're not officially collecting, add
1589cf7f2e2dSJohn Marino 		     to the collect list anyway.  */
1590cf7f2e2dSJohn Marino 		  add_aexpr (collect, aexpr);
1591cf7f2e2dSJohn Marino 
1592cf7f2e2dSJohn Marino 		  do_cleanups (old_chain);
1593cf7f2e2dSJohn Marino 		}		/* do */
1594cf7f2e2dSJohn Marino 	    }
1595cf7f2e2dSJohn Marino 	  while (action_exp && *action_exp++ == ',');
1596cf7f2e2dSJohn Marino 	}			/* if */
15975796c8dcSSimon Schubert       else if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
15985796c8dcSSimon Schubert 	{
1599cf7f2e2dSJohn Marino 	  /* We check against nested while-stepping when setting
1600cf7f2e2dSJohn Marino 	     breakpoint action, so no way to run into nested
1601cf7f2e2dSJohn Marino 	     here.  */
1602cf7f2e2dSJohn Marino 	  gdb_assert (stepping_list);
1603cf7f2e2dSJohn Marino 
1604cf7f2e2dSJohn Marino 	  encode_actions_1 (action->body_list[0], t, tloc, frame_reg,
1605cf7f2e2dSJohn Marino 			    frame_offset, stepping_list, NULL);
16065796c8dcSSimon Schubert 	}
16075796c8dcSSimon Schubert       else
1608cf7f2e2dSJohn Marino 	error (_("Invalid tracepoint command '%s'"), action->line);
16095796c8dcSSimon Schubert     }				/* for */
1610cf7f2e2dSJohn Marino }
1611cf7f2e2dSJohn Marino 
1612cf7f2e2dSJohn Marino /* Render all actions into gdb protocol.  */
1613*ef5ccd6cSJohn Marino 
1614*ef5ccd6cSJohn Marino void
encode_actions(struct breakpoint * t,struct bp_location * tloc,char *** tdp_actions,char *** stepping_actions)1615cf7f2e2dSJohn Marino encode_actions (struct breakpoint *t, struct bp_location *tloc,
1616cf7f2e2dSJohn Marino 		char ***tdp_actions, char ***stepping_actions)
1617cf7f2e2dSJohn Marino {
1618cf7f2e2dSJohn Marino   static char tdp_buff[2048], step_buff[2048];
1619cf7f2e2dSJohn Marino   char *default_collect_line = NULL;
1620cf7f2e2dSJohn Marino   struct command_line *actions;
1621cf7f2e2dSJohn Marino   struct command_line *default_collect_action = NULL;
1622cf7f2e2dSJohn Marino   int frame_reg;
1623cf7f2e2dSJohn Marino   LONGEST frame_offset;
1624cf7f2e2dSJohn Marino   struct cleanup *back_to;
1625cf7f2e2dSJohn Marino 
1626cf7f2e2dSJohn Marino   back_to = make_cleanup (null_cleanup, NULL);
1627cf7f2e2dSJohn Marino 
1628cf7f2e2dSJohn Marino   clear_collection_list (&tracepoint_list);
1629cf7f2e2dSJohn Marino   clear_collection_list (&stepping_list);
1630cf7f2e2dSJohn Marino 
1631cf7f2e2dSJohn Marino   *tdp_actions = NULL;
1632cf7f2e2dSJohn Marino   *stepping_actions = NULL;
1633cf7f2e2dSJohn Marino 
1634a45ae5f8SJohn Marino   gdbarch_virtual_frame_pointer (tloc->gdbarch,
1635a45ae5f8SJohn Marino 				 tloc->address, &frame_reg, &frame_offset);
1636cf7f2e2dSJohn Marino 
1637cf7f2e2dSJohn Marino   actions = breakpoint_commands (t);
1638cf7f2e2dSJohn Marino 
1639cf7f2e2dSJohn Marino   /* If there are default expressions to collect, make up a collect
1640cf7f2e2dSJohn Marino      action and prepend to the action list to encode.  Note that since
1641cf7f2e2dSJohn Marino      validation is per-tracepoint (local var "xyz" might be valid for
1642cf7f2e2dSJohn Marino      one tracepoint and not another, etc), we make up the action on
1643cf7f2e2dSJohn Marino      the fly, and don't cache it.  */
1644cf7f2e2dSJohn Marino   if (*default_collect)
1645cf7f2e2dSJohn Marino     {
1646cf7f2e2dSJohn Marino       char *line;
1647cf7f2e2dSJohn Marino 
1648cf7f2e2dSJohn Marino       default_collect_line =  xstrprintf ("collect %s", default_collect);
1649cf7f2e2dSJohn Marino       make_cleanup (xfree, default_collect_line);
1650cf7f2e2dSJohn Marino 
1651cf7f2e2dSJohn Marino       line = default_collect_line;
1652cf7f2e2dSJohn Marino       validate_actionline (&line, t);
1653cf7f2e2dSJohn Marino 
1654cf7f2e2dSJohn Marino       default_collect_action = xmalloc (sizeof (struct command_line));
1655cf7f2e2dSJohn Marino       make_cleanup (xfree, default_collect_action);
1656cf7f2e2dSJohn Marino       default_collect_action->next = actions;
1657cf7f2e2dSJohn Marino       default_collect_action->line = line;
1658cf7f2e2dSJohn Marino       actions = default_collect_action;
1659cf7f2e2dSJohn Marino     }
1660cf7f2e2dSJohn Marino   encode_actions_1 (actions, t, tloc, frame_reg, frame_offset,
1661cf7f2e2dSJohn Marino 		    &tracepoint_list, &stepping_list);
1662cf7f2e2dSJohn Marino 
16635796c8dcSSimon Schubert   memrange_sortmerge (&tracepoint_list);
16645796c8dcSSimon Schubert   memrange_sortmerge (&stepping_list);
16655796c8dcSSimon Schubert 
16665796c8dcSSimon Schubert   *tdp_actions = stringify_collection_list (&tracepoint_list,
16675796c8dcSSimon Schubert 					    tdp_buff);
16685796c8dcSSimon Schubert   *stepping_actions = stringify_collection_list (&stepping_list,
16695796c8dcSSimon Schubert 						 step_buff);
1670cf7f2e2dSJohn Marino 
1671cf7f2e2dSJohn Marino   do_cleanups (back_to);
16725796c8dcSSimon Schubert }
16735796c8dcSSimon Schubert 
16745796c8dcSSimon Schubert static void
add_aexpr(struct collection_list * collect,struct agent_expr * aexpr)16755796c8dcSSimon Schubert add_aexpr (struct collection_list *collect, struct agent_expr *aexpr)
16765796c8dcSSimon Schubert {
16775796c8dcSSimon Schubert   if (collect->next_aexpr_elt >= collect->aexpr_listsize)
16785796c8dcSSimon Schubert     {
16795796c8dcSSimon Schubert       collect->aexpr_list =
16805796c8dcSSimon Schubert 	xrealloc (collect->aexpr_list,
16815796c8dcSSimon Schubert 		  2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
16825796c8dcSSimon Schubert       collect->aexpr_listsize *= 2;
16835796c8dcSSimon Schubert     }
16845796c8dcSSimon Schubert   collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
16855796c8dcSSimon Schubert   collect->next_aexpr_elt++;
16865796c8dcSSimon Schubert }
16875796c8dcSSimon Schubert 
1688a45ae5f8SJohn Marino static void
process_tracepoint_on_disconnect(void)1689a45ae5f8SJohn Marino process_tracepoint_on_disconnect (void)
16905796c8dcSSimon Schubert {
1691cf7f2e2dSJohn Marino   VEC(breakpoint_p) *tp_vec = NULL;
1692cf7f2e2dSJohn Marino   int ix;
1693a45ae5f8SJohn Marino   struct breakpoint *b;
1694a45ae5f8SJohn Marino   int has_pending_p = 0;
1695a45ae5f8SJohn Marino 
1696a45ae5f8SJohn Marino   /* Check whether we still have pending tracepoint.  If we have, warn the
1697a45ae5f8SJohn Marino      user that pending tracepoint will no longer work.  */
1698a45ae5f8SJohn Marino   tp_vec = all_tracepoints ();
1699a45ae5f8SJohn Marino   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
1700a45ae5f8SJohn Marino     {
1701a45ae5f8SJohn Marino       if (b->loc == NULL)
1702a45ae5f8SJohn Marino 	{
1703a45ae5f8SJohn Marino 	  has_pending_p = 1;
1704a45ae5f8SJohn Marino 	  break;
1705a45ae5f8SJohn Marino 	}
1706a45ae5f8SJohn Marino       else
1707a45ae5f8SJohn Marino 	{
1708a45ae5f8SJohn Marino 	  struct bp_location *loc1;
1709a45ae5f8SJohn Marino 
1710a45ae5f8SJohn Marino 	  for (loc1 = b->loc; loc1; loc1 = loc1->next)
1711a45ae5f8SJohn Marino 	    {
1712a45ae5f8SJohn Marino 	      if (loc1->shlib_disabled)
1713a45ae5f8SJohn Marino 		{
1714a45ae5f8SJohn Marino 		  has_pending_p = 1;
1715a45ae5f8SJohn Marino 		  break;
1716a45ae5f8SJohn Marino 		}
1717a45ae5f8SJohn Marino 	    }
1718a45ae5f8SJohn Marino 
1719a45ae5f8SJohn Marino 	  if (has_pending_p)
1720a45ae5f8SJohn Marino 	    break;
1721a45ae5f8SJohn Marino 	}
1722a45ae5f8SJohn Marino     }
1723a45ae5f8SJohn Marino   VEC_free (breakpoint_p, tp_vec);
1724a45ae5f8SJohn Marino 
1725a45ae5f8SJohn Marino   if (has_pending_p)
1726a45ae5f8SJohn Marino     warning (_("Pending tracepoints will not be resolved while"
1727a45ae5f8SJohn Marino 	       " GDB is disconnected\n"));
1728a45ae5f8SJohn Marino }
1729a45ae5f8SJohn Marino 
1730a45ae5f8SJohn Marino 
1731a45ae5f8SJohn Marino void
start_tracing(char * notes)1732a45ae5f8SJohn Marino start_tracing (char *notes)
1733a45ae5f8SJohn Marino {
1734a45ae5f8SJohn Marino   VEC(breakpoint_p) *tp_vec = NULL;
1735a45ae5f8SJohn Marino   int ix;
1736a45ae5f8SJohn Marino   struct breakpoint *b;
1737cf7f2e2dSJohn Marino   struct trace_state_variable *tsv;
1738cf7f2e2dSJohn Marino   int any_enabled = 0, num_to_download = 0;
1739a45ae5f8SJohn Marino   int ret;
17405796c8dcSSimon Schubert 
1741cf7f2e2dSJohn Marino   tp_vec = all_tracepoints ();
17425796c8dcSSimon Schubert 
1743cf7f2e2dSJohn Marino   /* No point in tracing without any tracepoints...  */
1744cf7f2e2dSJohn Marino   if (VEC_length (breakpoint_p, tp_vec) == 0)
17455796c8dcSSimon Schubert     {
1746cf7f2e2dSJohn Marino       VEC_free (breakpoint_p, tp_vec);
1747cf7f2e2dSJohn Marino       error (_("No tracepoints defined, not starting trace"));
1748cf7f2e2dSJohn Marino     }
17495796c8dcSSimon Schubert 
1750a45ae5f8SJohn Marino   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
1751cf7f2e2dSJohn Marino     {
1752a45ae5f8SJohn Marino       struct tracepoint *t = (struct tracepoint *) b;
1753*ef5ccd6cSJohn Marino       struct bp_location *loc;
1754a45ae5f8SJohn Marino 
1755a45ae5f8SJohn Marino       if (b->enable_state == bp_enabled)
1756cf7f2e2dSJohn Marino 	any_enabled = 1;
1757cf7f2e2dSJohn Marino 
1758a45ae5f8SJohn Marino       if ((b->type == bp_fast_tracepoint
1759cf7f2e2dSJohn Marino 	   ? may_insert_fast_tracepoints
1760cf7f2e2dSJohn Marino 	   : may_insert_tracepoints))
1761cf7f2e2dSJohn Marino 	++num_to_download;
1762cf7f2e2dSJohn Marino       else
1763cf7f2e2dSJohn Marino 	warning (_("May not insert %stracepoints, skipping tracepoint %d"),
1764a45ae5f8SJohn Marino 		 (b->type == bp_fast_tracepoint ? "fast " : ""), b->number);
1765cf7f2e2dSJohn Marino     }
1766cf7f2e2dSJohn Marino 
1767cf7f2e2dSJohn Marino   if (!any_enabled)
1768cf7f2e2dSJohn Marino     {
1769a45ae5f8SJohn Marino       if (target_supports_enable_disable_tracepoint ())
1770a45ae5f8SJohn Marino 	warning (_("No tracepoints enabled"));
1771a45ae5f8SJohn Marino       else
1772a45ae5f8SJohn Marino 	{
1773a45ae5f8SJohn Marino 	  /* No point in tracing with only disabled tracepoints that
1774a45ae5f8SJohn Marino 	     cannot be re-enabled.  */
1775cf7f2e2dSJohn Marino 	  VEC_free (breakpoint_p, tp_vec);
1776cf7f2e2dSJohn Marino 	  error (_("No tracepoints enabled, not starting trace"));
1777cf7f2e2dSJohn Marino 	}
1778a45ae5f8SJohn Marino     }
1779cf7f2e2dSJohn Marino 
1780cf7f2e2dSJohn Marino   if (num_to_download <= 0)
1781cf7f2e2dSJohn Marino     {
1782cf7f2e2dSJohn Marino       VEC_free (breakpoint_p, tp_vec);
1783cf7f2e2dSJohn Marino       error (_("No tracepoints that may be downloaded, not starting trace"));
1784cf7f2e2dSJohn Marino     }
1785cf7f2e2dSJohn Marino 
1786cf7f2e2dSJohn Marino   target_trace_init ();
1787cf7f2e2dSJohn Marino 
1788a45ae5f8SJohn Marino   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
1789cf7f2e2dSJohn Marino     {
1790a45ae5f8SJohn Marino       struct tracepoint *t = (struct tracepoint *) b;
1791a45ae5f8SJohn Marino       struct bp_location *loc;
1792*ef5ccd6cSJohn Marino       int bp_location_downloaded = 0;
1793a45ae5f8SJohn Marino 
1794a45ae5f8SJohn Marino       /* Clear `inserted' flag.  */
1795a45ae5f8SJohn Marino       for (loc = b->loc; loc; loc = loc->next)
1796a45ae5f8SJohn Marino 	loc->inserted = 0;
1797a45ae5f8SJohn Marino 
1798a45ae5f8SJohn Marino       if ((b->type == bp_fast_tracepoint
1799cf7f2e2dSJohn Marino 	   ? !may_insert_fast_tracepoints
1800cf7f2e2dSJohn Marino 	   : !may_insert_tracepoints))
18015796c8dcSSimon Schubert 	continue;
18025796c8dcSSimon Schubert 
1803cf7f2e2dSJohn Marino       t->number_on_target = 0;
1804a45ae5f8SJohn Marino 
1805a45ae5f8SJohn Marino       for (loc = b->loc; loc; loc = loc->next)
1806a45ae5f8SJohn Marino 	{
1807a45ae5f8SJohn Marino 	  /* Since tracepoint locations are never duplicated, `inserted'
1808a45ae5f8SJohn Marino 	     flag should be zero.  */
1809a45ae5f8SJohn Marino 	  gdb_assert (!loc->inserted);
1810a45ae5f8SJohn Marino 
1811a45ae5f8SJohn Marino 	  target_download_tracepoint (loc);
1812a45ae5f8SJohn Marino 
1813a45ae5f8SJohn Marino 	  loc->inserted = 1;
1814*ef5ccd6cSJohn Marino 	  bp_location_downloaded = 1;
1815a45ae5f8SJohn Marino 	}
1816a45ae5f8SJohn Marino 
1817a45ae5f8SJohn Marino       t->number_on_target = b->number;
1818*ef5ccd6cSJohn Marino 
1819*ef5ccd6cSJohn Marino       for (loc = b->loc; loc; loc = loc->next)
1820*ef5ccd6cSJohn Marino 	if (loc->probe != NULL)
1821*ef5ccd6cSJohn Marino 	  loc->probe->pops->set_semaphore (loc->probe, loc->gdbarch);
1822*ef5ccd6cSJohn Marino 
1823*ef5ccd6cSJohn Marino       if (bp_location_downloaded)
1824*ef5ccd6cSJohn Marino 	observer_notify_breakpoint_modified (b);
18255796c8dcSSimon Schubert     }
1826cf7f2e2dSJohn Marino   VEC_free (breakpoint_p, tp_vec);
1827cf7f2e2dSJohn Marino 
1828cf7f2e2dSJohn Marino   /* Send down all the trace state variables too.  */
1829cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
18305796c8dcSSimon Schubert     {
1831cf7f2e2dSJohn Marino       target_download_trace_state_variable (tsv);
18325796c8dcSSimon Schubert     }
1833cf7f2e2dSJohn Marino 
1834cf7f2e2dSJohn Marino   /* Tell target to treat text-like sections as transparent.  */
1835cf7f2e2dSJohn Marino   target_trace_set_readonly_regions ();
1836cf7f2e2dSJohn Marino   /* Set some mode flags.  */
1837cf7f2e2dSJohn Marino   target_set_disconnected_tracing (disconnected_tracing);
1838cf7f2e2dSJohn Marino   target_set_circular_trace_buffer (circular_trace_buffer);
1839*ef5ccd6cSJohn Marino   target_set_trace_buffer_size (trace_buffer_size);
1840cf7f2e2dSJohn Marino 
1841a45ae5f8SJohn Marino   if (!notes)
1842a45ae5f8SJohn Marino     notes = trace_notes;
1843a45ae5f8SJohn Marino   ret = target_set_trace_notes (trace_user, notes, NULL);
1844a45ae5f8SJohn Marino 
1845a45ae5f8SJohn Marino   if (!ret && (trace_user || notes))
1846*ef5ccd6cSJohn Marino     warning (_("Target does not support trace user/notes, info ignored"));
1847a45ae5f8SJohn Marino 
1848cf7f2e2dSJohn Marino   /* Now insert traps and begin collecting data.  */
1849cf7f2e2dSJohn Marino   target_trace_start ();
1850cf7f2e2dSJohn Marino 
1851cf7f2e2dSJohn Marino   /* Reset our local state.  */
1852cf7f2e2dSJohn Marino   set_traceframe_num (-1);
1853cf7f2e2dSJohn Marino   set_tracepoint_num (-1);
1854cf7f2e2dSJohn Marino   set_traceframe_context (NULL);
1855cf7f2e2dSJohn Marino   current_trace_status()->running = 1;
1856c50c785cSJohn Marino   clear_traceframe_info ();
18575796c8dcSSimon Schubert }
18585796c8dcSSimon Schubert 
1859a45ae5f8SJohn Marino /* The tstart command requests the target to start a new trace run.
1860a45ae5f8SJohn Marino    The command passes any arguments it has to the target verbatim, as
1861a45ae5f8SJohn Marino    an optional "trace note".  This is useful as for instance a warning
1862a45ae5f8SJohn Marino    to other users if the trace runs disconnected, and you don't want
1863a45ae5f8SJohn Marino    anybody else messing with the target.  */
18645796c8dcSSimon Schubert 
18655796c8dcSSimon Schubert static void
trace_start_command(char * args,int from_tty)18665796c8dcSSimon Schubert trace_start_command (char *args, int from_tty)
18675796c8dcSSimon Schubert {
18685796c8dcSSimon Schubert   dont_repeat ();	/* Like "run", dangerous to repeat accidentally.  */
18695796c8dcSSimon Schubert 
1870cf7f2e2dSJohn Marino   if (current_trace_status ()->running)
18715796c8dcSSimon Schubert     {
1872cf7f2e2dSJohn Marino       if (from_tty
1873cf7f2e2dSJohn Marino 	  && !query (_("A trace is running already.  Start a new run? ")))
1874cf7f2e2dSJohn Marino 	error (_("New trace run not started."));
18755796c8dcSSimon Schubert     }
18765796c8dcSSimon Schubert 
1877a45ae5f8SJohn Marino   start_tracing (args);
18785796c8dcSSimon Schubert }
18795796c8dcSSimon Schubert 
1880a45ae5f8SJohn Marino /* The tstop command stops the tracing run.  The command passes any
1881a45ae5f8SJohn Marino    supplied arguments to the target verbatim as a "stop note"; if the
1882a45ae5f8SJohn Marino    target supports trace notes, then it will be reported back as part
1883a45ae5f8SJohn Marino    of the trace run's status.  */
1884a45ae5f8SJohn Marino 
18855796c8dcSSimon Schubert static void
trace_stop_command(char * args,int from_tty)18865796c8dcSSimon Schubert trace_stop_command (char *args, int from_tty)
18875796c8dcSSimon Schubert {
1888cf7f2e2dSJohn Marino   if (!current_trace_status ()->running)
1889cf7f2e2dSJohn Marino     error (_("Trace is not running."));
1890cf7f2e2dSJohn Marino 
1891a45ae5f8SJohn Marino   stop_tracing (args);
18925796c8dcSSimon Schubert }
18935796c8dcSSimon Schubert 
1894cf7f2e2dSJohn Marino void
stop_tracing(char * note)1895a45ae5f8SJohn Marino stop_tracing (char *note)
1896cf7f2e2dSJohn Marino {
1897a45ae5f8SJohn Marino   int ret;
1898*ef5ccd6cSJohn Marino   VEC(breakpoint_p) *tp_vec = NULL;
1899*ef5ccd6cSJohn Marino   int ix;
1900*ef5ccd6cSJohn Marino   struct breakpoint *t;
1901a45ae5f8SJohn Marino 
1902cf7f2e2dSJohn Marino   target_trace_stop ();
1903a45ae5f8SJohn Marino 
1904*ef5ccd6cSJohn Marino   tp_vec = all_tracepoints ();
1905*ef5ccd6cSJohn Marino   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
1906*ef5ccd6cSJohn Marino     {
1907*ef5ccd6cSJohn Marino       struct bp_location *loc;
1908*ef5ccd6cSJohn Marino 
1909*ef5ccd6cSJohn Marino       if ((t->type == bp_fast_tracepoint
1910*ef5ccd6cSJohn Marino 	   ? !may_insert_fast_tracepoints
1911*ef5ccd6cSJohn Marino 	   : !may_insert_tracepoints))
1912*ef5ccd6cSJohn Marino 	continue;
1913*ef5ccd6cSJohn Marino 
1914*ef5ccd6cSJohn Marino       for (loc = t->loc; loc; loc = loc->next)
1915*ef5ccd6cSJohn Marino 	{
1916*ef5ccd6cSJohn Marino 	  /* GDB can be totally absent in some disconnected trace scenarios,
1917*ef5ccd6cSJohn Marino 	     but we don't really care if this semaphore goes out of sync.
1918*ef5ccd6cSJohn Marino 	     That's why we are decrementing it here, but not taking care
1919*ef5ccd6cSJohn Marino 	     in other places.  */
1920*ef5ccd6cSJohn Marino 	  if (loc->probe != NULL)
1921*ef5ccd6cSJohn Marino 	    loc->probe->pops->clear_semaphore (loc->probe, loc->gdbarch);
1922*ef5ccd6cSJohn Marino 	}
1923*ef5ccd6cSJohn Marino     }
1924*ef5ccd6cSJohn Marino 
1925*ef5ccd6cSJohn Marino   VEC_free (breakpoint_p, tp_vec);
1926*ef5ccd6cSJohn Marino 
1927a45ae5f8SJohn Marino   if (!note)
1928a45ae5f8SJohn Marino     note = trace_stop_notes;
1929a45ae5f8SJohn Marino   ret = target_set_trace_notes (NULL, NULL, note);
1930a45ae5f8SJohn Marino 
1931a45ae5f8SJohn Marino   if (!ret && note)
1932*ef5ccd6cSJohn Marino     warning (_("Target does not support trace notes, note ignored"));
1933a45ae5f8SJohn Marino 
1934c50c785cSJohn Marino   /* Should change in response to reply?  */
1935cf7f2e2dSJohn Marino   current_trace_status ()->running = 0;
1936cf7f2e2dSJohn Marino }
19375796c8dcSSimon Schubert 
19385796c8dcSSimon Schubert /* tstatus command */
19395796c8dcSSimon Schubert static void
trace_status_command(char * args,int from_tty)19405796c8dcSSimon Schubert trace_status_command (char *args, int from_tty)
19415796c8dcSSimon Schubert {
1942cf7f2e2dSJohn Marino   struct trace_status *ts = current_trace_status ();
1943a45ae5f8SJohn Marino   int status, ix;
1944a45ae5f8SJohn Marino   VEC(breakpoint_p) *tp_vec = NULL;
1945a45ae5f8SJohn Marino   struct breakpoint *t;
1946cf7f2e2dSJohn Marino 
1947cf7f2e2dSJohn Marino   status = target_get_trace_status (ts);
1948cf7f2e2dSJohn Marino 
1949cf7f2e2dSJohn Marino   if (status == -1)
19505796c8dcSSimon Schubert     {
1951*ef5ccd6cSJohn Marino       if (ts->filename != NULL)
1952cf7f2e2dSJohn Marino 	printf_filtered (_("Using a trace file.\n"));
1953cf7f2e2dSJohn Marino       else
1954cf7f2e2dSJohn Marino 	{
1955cf7f2e2dSJohn Marino 	  printf_filtered (_("Trace can not be run on this target.\n"));
1956cf7f2e2dSJohn Marino 	  return;
1957cf7f2e2dSJohn Marino 	}
1958cf7f2e2dSJohn Marino     }
19595796c8dcSSimon Schubert 
1960cf7f2e2dSJohn Marino   if (!ts->running_known)
1961cf7f2e2dSJohn Marino     {
1962cf7f2e2dSJohn Marino       printf_filtered (_("Run/stop status is unknown.\n"));
1963cf7f2e2dSJohn Marino     }
1964cf7f2e2dSJohn Marino   else if (ts->running)
1965cf7f2e2dSJohn Marino     {
1966cf7f2e2dSJohn Marino       printf_filtered (_("Trace is running on the target.\n"));
19675796c8dcSSimon Schubert     }
19685796c8dcSSimon Schubert   else
1969cf7f2e2dSJohn Marino     {
1970cf7f2e2dSJohn Marino       switch (ts->stop_reason)
1971cf7f2e2dSJohn Marino 	{
1972cf7f2e2dSJohn Marino 	case trace_never_run:
1973cf7f2e2dSJohn Marino 	  printf_filtered (_("No trace has been run on the target.\n"));
1974cf7f2e2dSJohn Marino 	  break;
1975cf7f2e2dSJohn Marino 	case tstop_command:
1976a45ae5f8SJohn Marino 	  if (ts->stop_desc)
1977a45ae5f8SJohn Marino 	    printf_filtered (_("Trace stopped by a tstop command (%s).\n"),
1978a45ae5f8SJohn Marino 			     ts->stop_desc);
1979a45ae5f8SJohn Marino 	  else
1980cf7f2e2dSJohn Marino 	    printf_filtered (_("Trace stopped by a tstop command.\n"));
1981cf7f2e2dSJohn Marino 	  break;
1982cf7f2e2dSJohn Marino 	case trace_buffer_full:
1983cf7f2e2dSJohn Marino 	  printf_filtered (_("Trace stopped because the buffer was full.\n"));
1984cf7f2e2dSJohn Marino 	  break;
1985cf7f2e2dSJohn Marino 	case trace_disconnected:
1986cf7f2e2dSJohn Marino 	  printf_filtered (_("Trace stopped because of disconnection.\n"));
1987cf7f2e2dSJohn Marino 	  break;
1988cf7f2e2dSJohn Marino 	case tracepoint_passcount:
1989cf7f2e2dSJohn Marino 	  printf_filtered (_("Trace stopped by tracepoint %d.\n"),
1990cf7f2e2dSJohn Marino 			   ts->stopping_tracepoint);
1991cf7f2e2dSJohn Marino 	  break;
1992cf7f2e2dSJohn Marino 	case tracepoint_error:
1993cf7f2e2dSJohn Marino 	  if (ts->stopping_tracepoint)
1994c50c785cSJohn Marino 	    printf_filtered (_("Trace stopped by an "
1995c50c785cSJohn Marino 			       "error (%s, tracepoint %d).\n"),
1996a45ae5f8SJohn Marino 			     ts->stop_desc, ts->stopping_tracepoint);
1997cf7f2e2dSJohn Marino 	  else
1998cf7f2e2dSJohn Marino 	    printf_filtered (_("Trace stopped by an error (%s).\n"),
1999a45ae5f8SJohn Marino 			     ts->stop_desc);
2000cf7f2e2dSJohn Marino 	  break;
2001cf7f2e2dSJohn Marino 	case trace_stop_reason_unknown:
2002cf7f2e2dSJohn Marino 	  printf_filtered (_("Trace stopped for an unknown reason.\n"));
2003cf7f2e2dSJohn Marino 	  break;
2004cf7f2e2dSJohn Marino 	default:
2005cf7f2e2dSJohn Marino 	  printf_filtered (_("Trace stopped for some other reason (%d).\n"),
2006cf7f2e2dSJohn Marino 			   ts->stop_reason);
2007cf7f2e2dSJohn Marino 	  break;
2008cf7f2e2dSJohn Marino 	}
2009cf7f2e2dSJohn Marino     }
2010cf7f2e2dSJohn Marino 
2011cf7f2e2dSJohn Marino   if (ts->traceframes_created >= 0
2012cf7f2e2dSJohn Marino       && ts->traceframe_count != ts->traceframes_created)
2013cf7f2e2dSJohn Marino     {
2014c50c785cSJohn Marino       printf_filtered (_("Buffer contains %d trace "
2015c50c785cSJohn Marino 			 "frames (of %d created total).\n"),
2016cf7f2e2dSJohn Marino 		       ts->traceframe_count, ts->traceframes_created);
2017cf7f2e2dSJohn Marino     }
2018cf7f2e2dSJohn Marino   else if (ts->traceframe_count >= 0)
2019cf7f2e2dSJohn Marino     {
2020cf7f2e2dSJohn Marino       printf_filtered (_("Collected %d trace frames.\n"),
2021cf7f2e2dSJohn Marino 		       ts->traceframe_count);
2022cf7f2e2dSJohn Marino     }
2023cf7f2e2dSJohn Marino 
2024cf7f2e2dSJohn Marino   if (ts->buffer_free >= 0)
2025cf7f2e2dSJohn Marino     {
2026cf7f2e2dSJohn Marino       if (ts->buffer_size >= 0)
2027cf7f2e2dSJohn Marino 	{
2028cf7f2e2dSJohn Marino 	  printf_filtered (_("Trace buffer has %d bytes of %d bytes free"),
2029cf7f2e2dSJohn Marino 			   ts->buffer_free, ts->buffer_size);
2030cf7f2e2dSJohn Marino 	  if (ts->buffer_size > 0)
2031cf7f2e2dSJohn Marino 	    printf_filtered (_(" (%d%% full)"),
2032cf7f2e2dSJohn Marino 			     ((int) ((((long long) (ts->buffer_size
2033cf7f2e2dSJohn Marino 						    - ts->buffer_free)) * 100)
2034cf7f2e2dSJohn Marino 				     / ts->buffer_size)));
2035cf7f2e2dSJohn Marino 	  printf_filtered (_(".\n"));
2036cf7f2e2dSJohn Marino 	}
2037cf7f2e2dSJohn Marino       else
2038cf7f2e2dSJohn Marino 	printf_filtered (_("Trace buffer has %d bytes free.\n"),
2039cf7f2e2dSJohn Marino 			 ts->buffer_free);
2040cf7f2e2dSJohn Marino     }
2041cf7f2e2dSJohn Marino 
2042cf7f2e2dSJohn Marino   if (ts->disconnected_tracing)
2043cf7f2e2dSJohn Marino     printf_filtered (_("Trace will continue if GDB disconnects.\n"));
2044cf7f2e2dSJohn Marino   else
2045cf7f2e2dSJohn Marino     printf_filtered (_("Trace will stop if GDB disconnects.\n"));
2046cf7f2e2dSJohn Marino 
2047cf7f2e2dSJohn Marino   if (ts->circular_buffer)
2048cf7f2e2dSJohn Marino     printf_filtered (_("Trace buffer is circular.\n"));
2049cf7f2e2dSJohn Marino 
2050a45ae5f8SJohn Marino   if (ts->user_name && strlen (ts->user_name) > 0)
2051a45ae5f8SJohn Marino     printf_filtered (_("Trace user is %s.\n"), ts->user_name);
2052a45ae5f8SJohn Marino 
2053a45ae5f8SJohn Marino   if (ts->notes && strlen (ts->notes) > 0)
2054a45ae5f8SJohn Marino     printf_filtered (_("Trace notes: %s.\n"), ts->notes);
2055a45ae5f8SJohn Marino 
2056cf7f2e2dSJohn Marino   /* Now report on what we're doing with tfind.  */
2057cf7f2e2dSJohn Marino   if (traceframe_number >= 0)
2058cf7f2e2dSJohn Marino     printf_filtered (_("Looking at trace frame %d, tracepoint %d.\n"),
2059cf7f2e2dSJohn Marino 		     traceframe_number, tracepoint_number);
2060cf7f2e2dSJohn Marino   else
2061cf7f2e2dSJohn Marino     printf_filtered (_("Not looking at any trace frame.\n"));
2062a45ae5f8SJohn Marino 
2063a45ae5f8SJohn Marino   /* Report start/stop times if supplied.  */
2064a45ae5f8SJohn Marino   if (ts->start_time)
2065a45ae5f8SJohn Marino     {
2066a45ae5f8SJohn Marino       if (ts->stop_time)
2067a45ae5f8SJohn Marino 	{
2068a45ae5f8SJohn Marino 	  LONGEST run_time = ts->stop_time - ts->start_time;
2069a45ae5f8SJohn Marino 
2070a45ae5f8SJohn Marino 	  /* Reporting a run time is more readable than two long numbers.  */
2071a45ae5f8SJohn Marino 	  printf_filtered (_("Trace started at %ld.%06ld secs, stopped %ld.%06ld secs later.\n"),
2072a45ae5f8SJohn Marino 			   (long int) ts->start_time / 1000000,
2073a45ae5f8SJohn Marino 			   (long int) ts->start_time % 1000000,
2074a45ae5f8SJohn Marino 			   (long int) run_time / 1000000,
2075a45ae5f8SJohn Marino 			   (long int) run_time % 1000000);
2076a45ae5f8SJohn Marino 	}
2077a45ae5f8SJohn Marino       else
2078a45ae5f8SJohn Marino 	printf_filtered (_("Trace started at %ld.%06ld secs.\n"),
2079a45ae5f8SJohn Marino 			 (long int) ts->start_time / 1000000,
2080a45ae5f8SJohn Marino 			 (long int) ts->start_time % 1000000);
2081a45ae5f8SJohn Marino     }
2082a45ae5f8SJohn Marino   else if (ts->stop_time)
2083a45ae5f8SJohn Marino     printf_filtered (_("Trace stopped at %ld.%06ld secs.\n"),
2084a45ae5f8SJohn Marino 		     (long int) ts->stop_time / 1000000,
2085a45ae5f8SJohn Marino 		     (long int) ts->stop_time % 1000000);
2086a45ae5f8SJohn Marino 
2087a45ae5f8SJohn Marino   /* Now report any per-tracepoint status available.  */
2088a45ae5f8SJohn Marino   tp_vec = all_tracepoints ();
2089a45ae5f8SJohn Marino 
2090a45ae5f8SJohn Marino   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, t); ix++)
2091a45ae5f8SJohn Marino     target_get_tracepoint_status (t, NULL);
2092a45ae5f8SJohn Marino 
2093a45ae5f8SJohn Marino   VEC_free (breakpoint_p, tp_vec);
2094cf7f2e2dSJohn Marino }
2095cf7f2e2dSJohn Marino 
2096cf7f2e2dSJohn Marino /* Report the trace status to uiout, in a way suitable for MI, and not
2097cf7f2e2dSJohn Marino    suitable for CLI.  If ON_STOP is true, suppress a few fields that
2098cf7f2e2dSJohn Marino    are not meaningful in the -trace-stop response.
2099cf7f2e2dSJohn Marino 
2100cf7f2e2dSJohn Marino    The implementation is essentially parallel to trace_status_command, but
2101cf7f2e2dSJohn Marino    merging them will result in unreadable code.  */
2102cf7f2e2dSJohn Marino void
trace_status_mi(int on_stop)2103cf7f2e2dSJohn Marino trace_status_mi (int on_stop)
2104cf7f2e2dSJohn Marino {
2105a45ae5f8SJohn Marino   struct ui_out *uiout = current_uiout;
2106cf7f2e2dSJohn Marino   struct trace_status *ts = current_trace_status ();
2107cf7f2e2dSJohn Marino   int status;
2108cf7f2e2dSJohn Marino 
2109cf7f2e2dSJohn Marino   status = target_get_trace_status (ts);
2110cf7f2e2dSJohn Marino 
2111*ef5ccd6cSJohn Marino   if (status == -1 && ts->filename == NULL)
2112cf7f2e2dSJohn Marino     {
2113cf7f2e2dSJohn Marino       ui_out_field_string (uiout, "supported", "0");
2114cf7f2e2dSJohn Marino       return;
2115cf7f2e2dSJohn Marino     }
2116cf7f2e2dSJohn Marino 
2117*ef5ccd6cSJohn Marino   if (ts->filename != NULL)
2118cf7f2e2dSJohn Marino     ui_out_field_string (uiout, "supported", "file");
2119cf7f2e2dSJohn Marino   else if (!on_stop)
2120cf7f2e2dSJohn Marino     ui_out_field_string (uiout, "supported", "1");
2121cf7f2e2dSJohn Marino 
2122*ef5ccd6cSJohn Marino   if (ts->filename != NULL)
2123*ef5ccd6cSJohn Marino     ui_out_field_string (uiout, "trace-file", ts->filename);
2124*ef5ccd6cSJohn Marino 
2125cf7f2e2dSJohn Marino   gdb_assert (ts->running_known);
2126cf7f2e2dSJohn Marino 
2127cf7f2e2dSJohn Marino   if (ts->running)
2128cf7f2e2dSJohn Marino     {
2129cf7f2e2dSJohn Marino       ui_out_field_string (uiout, "running", "1");
2130cf7f2e2dSJohn Marino 
2131cf7f2e2dSJohn Marino       /* Unlike CLI, do not show the state of 'disconnected-tracing' variable.
2132cf7f2e2dSJohn Marino 	 Given that the frontend gets the status either on -trace-stop, or from
2133cf7f2e2dSJohn Marino 	 -trace-status after re-connection, it does not seem like this
2134cf7f2e2dSJohn Marino 	 information is necessary for anything.  It is not necessary for either
2135cf7f2e2dSJohn Marino 	 figuring the vital state of the target nor for navigation of trace
2136cf7f2e2dSJohn Marino 	 frames.  If the frontend wants to show the current state is some
2137cf7f2e2dSJohn Marino 	 configure dialog, it can request the value when such dialog is
2138cf7f2e2dSJohn Marino 	 invoked by the user.  */
2139cf7f2e2dSJohn Marino     }
2140cf7f2e2dSJohn Marino   else
2141cf7f2e2dSJohn Marino     {
2142cf7f2e2dSJohn Marino       char *stop_reason = NULL;
2143cf7f2e2dSJohn Marino       int stopping_tracepoint = -1;
2144cf7f2e2dSJohn Marino 
2145cf7f2e2dSJohn Marino       if (!on_stop)
2146cf7f2e2dSJohn Marino 	ui_out_field_string (uiout, "running", "0");
2147cf7f2e2dSJohn Marino 
2148cf7f2e2dSJohn Marino       if (ts->stop_reason != trace_stop_reason_unknown)
2149cf7f2e2dSJohn Marino 	{
2150cf7f2e2dSJohn Marino 	  switch (ts->stop_reason)
2151cf7f2e2dSJohn Marino 	    {
2152cf7f2e2dSJohn Marino 	    case tstop_command:
2153cf7f2e2dSJohn Marino 	      stop_reason = "request";
2154cf7f2e2dSJohn Marino 	      break;
2155cf7f2e2dSJohn Marino 	    case trace_buffer_full:
2156cf7f2e2dSJohn Marino 	      stop_reason = "overflow";
2157cf7f2e2dSJohn Marino 	      break;
2158cf7f2e2dSJohn Marino 	    case trace_disconnected:
2159cf7f2e2dSJohn Marino 	      stop_reason = "disconnection";
2160cf7f2e2dSJohn Marino 	      break;
2161cf7f2e2dSJohn Marino 	    case tracepoint_passcount:
2162cf7f2e2dSJohn Marino 	      stop_reason = "passcount";
2163cf7f2e2dSJohn Marino 	      stopping_tracepoint = ts->stopping_tracepoint;
2164cf7f2e2dSJohn Marino 	      break;
2165cf7f2e2dSJohn Marino 	    case tracepoint_error:
2166cf7f2e2dSJohn Marino 	      stop_reason = "error";
2167cf7f2e2dSJohn Marino 	      stopping_tracepoint = ts->stopping_tracepoint;
2168cf7f2e2dSJohn Marino 	      break;
2169cf7f2e2dSJohn Marino 	    }
2170cf7f2e2dSJohn Marino 
2171cf7f2e2dSJohn Marino 	  if (stop_reason)
2172cf7f2e2dSJohn Marino 	    {
2173cf7f2e2dSJohn Marino 	      ui_out_field_string (uiout, "stop-reason", stop_reason);
2174cf7f2e2dSJohn Marino 	      if (stopping_tracepoint != -1)
2175cf7f2e2dSJohn Marino 		ui_out_field_int (uiout, "stopping-tracepoint",
2176cf7f2e2dSJohn Marino 				  stopping_tracepoint);
2177cf7f2e2dSJohn Marino 	      if (ts->stop_reason == tracepoint_error)
2178cf7f2e2dSJohn Marino 		ui_out_field_string (uiout, "error-description",
2179a45ae5f8SJohn Marino 				     ts->stop_desc);
2180cf7f2e2dSJohn Marino 	    }
2181cf7f2e2dSJohn Marino 	}
2182cf7f2e2dSJohn Marino     }
2183cf7f2e2dSJohn Marino 
2184cf7f2e2dSJohn Marino   if (ts->traceframe_count != -1)
2185cf7f2e2dSJohn Marino     ui_out_field_int (uiout, "frames", ts->traceframe_count);
2186cf7f2e2dSJohn Marino   if (ts->traceframes_created != -1)
2187cf7f2e2dSJohn Marino     ui_out_field_int (uiout, "frames-created", ts->traceframes_created);
2188cf7f2e2dSJohn Marino   if (ts->buffer_size != -1)
2189cf7f2e2dSJohn Marino     ui_out_field_int (uiout, "buffer-size", ts->buffer_size);
2190cf7f2e2dSJohn Marino   if (ts->buffer_free != -1)
2191cf7f2e2dSJohn Marino     ui_out_field_int (uiout, "buffer-free", ts->buffer_free);
2192cf7f2e2dSJohn Marino 
2193cf7f2e2dSJohn Marino   ui_out_field_int (uiout, "disconnected",  ts->disconnected_tracing);
2194cf7f2e2dSJohn Marino   ui_out_field_int (uiout, "circular",  ts->circular_buffer);
2195a45ae5f8SJohn Marino 
2196a45ae5f8SJohn Marino   ui_out_field_string (uiout, "user-name", ts->user_name);
2197a45ae5f8SJohn Marino   ui_out_field_string (uiout, "notes", ts->notes);
2198a45ae5f8SJohn Marino 
2199a45ae5f8SJohn Marino   {
2200a45ae5f8SJohn Marino     char buf[100];
2201a45ae5f8SJohn Marino 
2202a45ae5f8SJohn Marino     xsnprintf (buf, sizeof buf, "%ld.%06ld",
2203a45ae5f8SJohn Marino 	       (long int) ts->start_time / 1000000,
2204a45ae5f8SJohn Marino 	       (long int) ts->start_time % 1000000);
2205a45ae5f8SJohn Marino     ui_out_field_string (uiout, "start-time", buf);
2206a45ae5f8SJohn Marino     xsnprintf (buf, sizeof buf, "%ld.%06ld",
2207a45ae5f8SJohn Marino 	       (long int) ts->stop_time / 1000000,
2208a45ae5f8SJohn Marino 	       (long int) ts->stop_time % 1000000);
2209a45ae5f8SJohn Marino     ui_out_field_string (uiout, "stop-time", buf);
2210a45ae5f8SJohn Marino   }
2211cf7f2e2dSJohn Marino }
2212cf7f2e2dSJohn Marino 
2213cf7f2e2dSJohn Marino /* This function handles the details of what to do about an ongoing
2214cf7f2e2dSJohn Marino    tracing run if the user has asked to detach or otherwise disconnect
2215cf7f2e2dSJohn Marino    from the target.  */
2216cf7f2e2dSJohn Marino void
disconnect_tracing(int from_tty)2217cf7f2e2dSJohn Marino disconnect_tracing (int from_tty)
2218cf7f2e2dSJohn Marino {
2219cf7f2e2dSJohn Marino   /* It can happen that the target that was tracing went away on its
2220cf7f2e2dSJohn Marino      own, and we didn't notice.  Get a status update, and if the
2221cf7f2e2dSJohn Marino      current target doesn't even do tracing, then assume it's not
2222cf7f2e2dSJohn Marino      running anymore.  */
2223cf7f2e2dSJohn Marino   if (target_get_trace_status (current_trace_status ()) < 0)
2224cf7f2e2dSJohn Marino     current_trace_status ()->running = 0;
2225cf7f2e2dSJohn Marino 
2226cf7f2e2dSJohn Marino   /* If running interactively, give the user the option to cancel and
2227cf7f2e2dSJohn Marino      then decide what to do differently with the run.  Scripts are
2228cf7f2e2dSJohn Marino      just going to disconnect and let the target deal with it,
2229cf7f2e2dSJohn Marino      according to how it's been instructed previously via
2230cf7f2e2dSJohn Marino      disconnected-tracing.  */
2231cf7f2e2dSJohn Marino   if (current_trace_status ()->running && from_tty)
2232cf7f2e2dSJohn Marino     {
2233a45ae5f8SJohn Marino       process_tracepoint_on_disconnect ();
2234a45ae5f8SJohn Marino 
2235cf7f2e2dSJohn Marino       if (current_trace_status ()->disconnected_tracing)
2236cf7f2e2dSJohn Marino 	{
2237c50c785cSJohn Marino 	  if (!query (_("Trace is running and will "
2238c50c785cSJohn Marino 			"continue after detach; detach anyway? ")))
2239cf7f2e2dSJohn Marino 	    error (_("Not confirmed."));
2240cf7f2e2dSJohn Marino 	}
2241cf7f2e2dSJohn Marino       else
2242cf7f2e2dSJohn Marino 	{
2243c50c785cSJohn Marino 	  if (!query (_("Trace is running but will "
2244c50c785cSJohn Marino 			"stop on detach; detach anyway? ")))
2245cf7f2e2dSJohn Marino 	    error (_("Not confirmed."));
2246cf7f2e2dSJohn Marino 	}
2247cf7f2e2dSJohn Marino     }
2248cf7f2e2dSJohn Marino 
2249cf7f2e2dSJohn Marino   /* Also we want to be out of tfind mode, otherwise things can get
2250cf7f2e2dSJohn Marino      confusing upon reconnection.  Just use these calls instead of
2251cf7f2e2dSJohn Marino      full tfind_1 behavior because we're in the middle of detaching,
2252cf7f2e2dSJohn Marino      and there's no point to updating current stack frame etc.  */
2253c50c785cSJohn Marino   set_current_traceframe (-1);
2254*ef5ccd6cSJohn Marino   set_tracepoint_num (-1);
2255cf7f2e2dSJohn Marino   set_traceframe_context (NULL);
22565796c8dcSSimon Schubert }
22575796c8dcSSimon Schubert 
22585796c8dcSSimon Schubert /* Worker function for the various flavors of the tfind command.  */
2259cf7f2e2dSJohn Marino void
tfind_1(enum trace_find_type type,int num,ULONGEST addr1,ULONGEST addr2,int from_tty)2260cf7f2e2dSJohn Marino tfind_1 (enum trace_find_type type, int num,
2261cf7f2e2dSJohn Marino 	 ULONGEST addr1, ULONGEST addr2,
22625796c8dcSSimon Schubert 	 int from_tty)
22635796c8dcSSimon Schubert {
22645796c8dcSSimon Schubert   int target_frameno = -1, target_tracept = -1;
2265cf7f2e2dSJohn Marino   struct frame_id old_frame_id = null_frame_id;
2266a45ae5f8SJohn Marino   struct tracepoint *tp;
2267a45ae5f8SJohn Marino   struct ui_out *uiout = current_uiout;
22685796c8dcSSimon Schubert 
2269cf7f2e2dSJohn Marino   /* Only try to get the current stack frame if we have a chance of
2270cf7f2e2dSJohn Marino      succeeding.  In particular, if we're trying to get a first trace
2271cf7f2e2dSJohn Marino      frame while all threads are running, it's not going to succeed,
2272cf7f2e2dSJohn Marino      so leave it with a default value and let the frame comparison
2273cf7f2e2dSJohn Marino      below (correctly) decide to print out the source location of the
2274cf7f2e2dSJohn Marino      trace frame.  */
2275cf7f2e2dSJohn Marino   if (!(type == tfind_number && num == -1)
2276cf7f2e2dSJohn Marino       && (has_stack_frames () || traceframe_number >= 0))
22775796c8dcSSimon Schubert     old_frame_id = get_frame_id (get_current_frame ());
22785796c8dcSSimon Schubert 
2279cf7f2e2dSJohn Marino   target_frameno = target_trace_find (type, num, addr1, addr2,
2280cf7f2e2dSJohn Marino 				      &target_tracept);
22815796c8dcSSimon Schubert 
2282cf7f2e2dSJohn Marino   if (type == tfind_number
2283cf7f2e2dSJohn Marino       && num == -1
2284cf7f2e2dSJohn Marino       && target_frameno == -1)
22855796c8dcSSimon Schubert     {
2286cf7f2e2dSJohn Marino       /* We told the target to get out of tfind mode, and it did.  */
2287cf7f2e2dSJohn Marino     }
2288cf7f2e2dSJohn Marino   else if (target_frameno == -1)
22895796c8dcSSimon Schubert     {
2290cf7f2e2dSJohn Marino       /* A request for a non-existent trace frame has failed.
22915796c8dcSSimon Schubert 	 Our response will be different, depending on FROM_TTY:
22925796c8dcSSimon Schubert 
22935796c8dcSSimon Schubert 	 If FROM_TTY is true, meaning that this command was
22945796c8dcSSimon Schubert 	 typed interactively by the user, then give an error
22955796c8dcSSimon Schubert 	 and DO NOT change the state of traceframe_number etc.
22965796c8dcSSimon Schubert 
22975796c8dcSSimon Schubert 	 However if FROM_TTY is false, meaning that we're either
22985796c8dcSSimon Schubert 	 in a script, a loop, or a user-defined command, then
22995796c8dcSSimon Schubert 	 DON'T give an error, but DO change the state of
23005796c8dcSSimon Schubert 	 traceframe_number etc. to invalid.
23015796c8dcSSimon Schubert 
23025796c8dcSSimon Schubert 	 The rationalle is that if you typed the command, you
23035796c8dcSSimon Schubert 	 might just have committed a typo or something, and you'd
23045796c8dcSSimon Schubert 	 like to NOT lose your current debugging state.  However
23055796c8dcSSimon Schubert 	 if you're in a user-defined command or especially in a
23065796c8dcSSimon Schubert 	 loop, then you need a way to detect that the command
23075796c8dcSSimon Schubert 	 failed WITHOUT aborting.  This allows you to write
23085796c8dcSSimon Schubert 	 scripts that search thru the trace buffer until the end,
23095796c8dcSSimon Schubert 	 and then continue on to do something else.  */
23105796c8dcSSimon Schubert 
23115796c8dcSSimon Schubert       if (from_tty)
23125796c8dcSSimon Schubert 	error (_("Target failed to find requested trace frame."));
23135796c8dcSSimon Schubert       else
23145796c8dcSSimon Schubert 	{
23155796c8dcSSimon Schubert 	  if (info_verbose)
23165796c8dcSSimon Schubert 	    printf_filtered ("End of trace buffer.\n");
2317cf7f2e2dSJohn Marino #if 0 /* dubious now?  */
23185796c8dcSSimon Schubert 	  /* The following will not recurse, since it's
23195796c8dcSSimon Schubert 	     special-cased.  */
23205796c8dcSSimon Schubert 	  trace_find_command ("-1", from_tty);
2321cf7f2e2dSJohn Marino #endif
23225796c8dcSSimon Schubert 	}
23235796c8dcSSimon Schubert     }
2324cf7f2e2dSJohn Marino 
2325cf7f2e2dSJohn Marino   tp = get_tracepoint_by_number_on_target (target_tracept);
23265796c8dcSSimon Schubert 
23275796c8dcSSimon Schubert   reinit_frame_cache ();
2328cf7f2e2dSJohn Marino   target_dcache_invalidate ();
2329*ef5ccd6cSJohn Marino 
2330a45ae5f8SJohn Marino   set_tracepoint_num (tp ? tp->base.number : target_tracept);
2331*ef5ccd6cSJohn Marino 
2332*ef5ccd6cSJohn Marino   if (target_frameno != get_traceframe_number ())
2333*ef5ccd6cSJohn Marino     observer_notify_traceframe_changed (target_frameno, tracepoint_number);
2334*ef5ccd6cSJohn Marino 
2335*ef5ccd6cSJohn Marino   set_current_traceframe (target_frameno);
2336*ef5ccd6cSJohn Marino 
23375796c8dcSSimon Schubert   if (target_frameno == -1)
23385796c8dcSSimon Schubert     set_traceframe_context (NULL);
23395796c8dcSSimon Schubert   else
23405796c8dcSSimon Schubert     set_traceframe_context (get_current_frame ());
23415796c8dcSSimon Schubert 
2342cf7f2e2dSJohn Marino   if (traceframe_number >= 0)
2343cf7f2e2dSJohn Marino     {
2344cf7f2e2dSJohn Marino       /* Use different branches for MI and CLI to make CLI messages
2345cf7f2e2dSJohn Marino 	 i18n-eable.  */
2346cf7f2e2dSJohn Marino       if (ui_out_is_mi_like_p (uiout))
2347cf7f2e2dSJohn Marino 	{
2348cf7f2e2dSJohn Marino 	  ui_out_field_string (uiout, "found", "1");
2349cf7f2e2dSJohn Marino 	  ui_out_field_int (uiout, "tracepoint", tracepoint_number);
2350cf7f2e2dSJohn Marino 	  ui_out_field_int (uiout, "traceframe", traceframe_number);
2351cf7f2e2dSJohn Marino 	}
2352cf7f2e2dSJohn Marino       else
2353cf7f2e2dSJohn Marino 	{
2354cf7f2e2dSJohn Marino 	  printf_unfiltered (_("Found trace frame %d, tracepoint %d\n"),
2355cf7f2e2dSJohn Marino 			     traceframe_number, tracepoint_number);
2356cf7f2e2dSJohn Marino 	}
2357cf7f2e2dSJohn Marino     }
2358cf7f2e2dSJohn Marino   else
2359cf7f2e2dSJohn Marino     {
2360cf7f2e2dSJohn Marino       if (ui_out_is_mi_like_p (uiout))
2361cf7f2e2dSJohn Marino 	ui_out_field_string (uiout, "found", "0");
2362cf7f2e2dSJohn Marino       else if (type == tfind_number && num == -1)
2363cf7f2e2dSJohn Marino 	printf_unfiltered (_("No longer looking at any trace frame\n"));
2364c50c785cSJohn Marino       else /* This case may never occur, check.  */
2365cf7f2e2dSJohn Marino 	printf_unfiltered (_("No trace frame found\n"));
2366cf7f2e2dSJohn Marino     }
2367cf7f2e2dSJohn Marino 
2368cf7f2e2dSJohn Marino   /* If we're in nonstop mode and getting out of looking at trace
2369cf7f2e2dSJohn Marino      frames, there won't be any current frame to go back to and
2370cf7f2e2dSJohn Marino      display.  */
2371cf7f2e2dSJohn Marino   if (from_tty
2372cf7f2e2dSJohn Marino       && (has_stack_frames () || traceframe_number >= 0))
23735796c8dcSSimon Schubert     {
23745796c8dcSSimon Schubert       enum print_what print_what;
23755796c8dcSSimon Schubert 
2376cf7f2e2dSJohn Marino       /* NOTE: in imitation of the step command, try to determine
23775796c8dcSSimon Schubert          whether we have made a transition from one function to
23785796c8dcSSimon Schubert          another.  If so, we'll print the "stack frame" (ie. the new
23795796c8dcSSimon Schubert          function and it's arguments) -- otherwise we'll just show the
23805796c8dcSSimon Schubert          new source line.  */
23815796c8dcSSimon Schubert 
23825796c8dcSSimon Schubert       if (frame_id_eq (old_frame_id,
23835796c8dcSSimon Schubert 		       get_frame_id (get_current_frame ())))
23845796c8dcSSimon Schubert 	print_what = SRC_LINE;
23855796c8dcSSimon Schubert       else
23865796c8dcSSimon Schubert 	print_what = SRC_AND_LOC;
23875796c8dcSSimon Schubert 
23885796c8dcSSimon Schubert       print_stack_frame (get_selected_frame (NULL), 1, print_what);
23895796c8dcSSimon Schubert       do_displays ();
23905796c8dcSSimon Schubert     }
23915796c8dcSSimon Schubert }
23925796c8dcSSimon Schubert 
23935796c8dcSSimon Schubert /* trace_find_command takes a trace frame number n,
23945796c8dcSSimon Schubert    sends "QTFrame:<n>" to the target,
23955796c8dcSSimon Schubert    and accepts a reply that may contain several optional pieces
23965796c8dcSSimon Schubert    of information: a frame number, a tracepoint number, and an
23975796c8dcSSimon Schubert    indication of whether this is a trap frame or a stepping frame.
23985796c8dcSSimon Schubert 
23995796c8dcSSimon Schubert    The minimal response is just "OK" (which indicates that the
24005796c8dcSSimon Schubert    target does not give us a frame number or a tracepoint number).
24015796c8dcSSimon Schubert    Instead of that, the target may send us a string containing
24025796c8dcSSimon Schubert    any combination of:
24035796c8dcSSimon Schubert    F<hexnum>    (gives the selected frame number)
24045796c8dcSSimon Schubert    T<hexnum>    (gives the selected tracepoint number)
24055796c8dcSSimon Schubert  */
24065796c8dcSSimon Schubert 
24075796c8dcSSimon Schubert /* tfind command */
24085796c8dcSSimon Schubert static void
trace_find_command(char * args,int from_tty)24095796c8dcSSimon Schubert trace_find_command (char *args, int from_tty)
2410c50c785cSJohn Marino { /* This should only be called with a numeric argument.  */
24115796c8dcSSimon Schubert   int frameno = -1;
24125796c8dcSSimon Schubert 
2413*ef5ccd6cSJohn Marino   if (current_trace_status ()->running
2414*ef5ccd6cSJohn Marino       && current_trace_status ()->filename == NULL)
2415c50c785cSJohn Marino     error (_("May not look at trace frames while trace is running."));
24165796c8dcSSimon Schubert 
24175796c8dcSSimon Schubert   if (args == 0 || *args == 0)
24185796c8dcSSimon Schubert     { /* TFIND with no args means find NEXT trace frame.  */
24195796c8dcSSimon Schubert       if (traceframe_number == -1)
2420c50c785cSJohn Marino 	frameno = 0;	/* "next" is first one.  */
24215796c8dcSSimon Schubert         else
24225796c8dcSSimon Schubert 	frameno = traceframe_number + 1;
24235796c8dcSSimon Schubert     }
24245796c8dcSSimon Schubert   else if (0 == strcmp (args, "-"))
24255796c8dcSSimon Schubert     {
24265796c8dcSSimon Schubert       if (traceframe_number == -1)
24275796c8dcSSimon Schubert 	error (_("not debugging trace buffer"));
24285796c8dcSSimon Schubert       else if (from_tty && traceframe_number == 0)
24295796c8dcSSimon Schubert 	error (_("already at start of trace buffer"));
24305796c8dcSSimon Schubert 
24315796c8dcSSimon Schubert       frameno = traceframe_number - 1;
24325796c8dcSSimon Schubert       }
2433cf7f2e2dSJohn Marino   /* A hack to work around eval's need for fp to have been collected.  */
2434cf7f2e2dSJohn Marino   else if (0 == strcmp (args, "-1"))
2435cf7f2e2dSJohn Marino     frameno = -1;
24365796c8dcSSimon Schubert   else
24375796c8dcSSimon Schubert     frameno = parse_and_eval_long (args);
24385796c8dcSSimon Schubert 
24395796c8dcSSimon Schubert   if (frameno < -1)
24405796c8dcSSimon Schubert     error (_("invalid input (%d is less than zero)"), frameno);
24415796c8dcSSimon Schubert 
2442cf7f2e2dSJohn Marino   tfind_1 (tfind_number, frameno, 0, 0, from_tty);
24435796c8dcSSimon Schubert }
24445796c8dcSSimon Schubert 
24455796c8dcSSimon Schubert /* tfind end */
24465796c8dcSSimon Schubert static void
trace_find_end_command(char * args,int from_tty)24475796c8dcSSimon Schubert trace_find_end_command (char *args, int from_tty)
24485796c8dcSSimon Schubert {
24495796c8dcSSimon Schubert   trace_find_command ("-1", from_tty);
24505796c8dcSSimon Schubert }
24515796c8dcSSimon Schubert 
24525796c8dcSSimon Schubert /* tfind start */
24535796c8dcSSimon Schubert static void
trace_find_start_command(char * args,int from_tty)24545796c8dcSSimon Schubert trace_find_start_command (char *args, int from_tty)
24555796c8dcSSimon Schubert {
24565796c8dcSSimon Schubert   trace_find_command ("0", from_tty);
24575796c8dcSSimon Schubert }
24585796c8dcSSimon Schubert 
24595796c8dcSSimon Schubert /* tfind pc command */
24605796c8dcSSimon Schubert static void
trace_find_pc_command(char * args,int from_tty)24615796c8dcSSimon Schubert trace_find_pc_command (char *args, int from_tty)
24625796c8dcSSimon Schubert {
24635796c8dcSSimon Schubert   CORE_ADDR pc;
24645796c8dcSSimon Schubert 
2465*ef5ccd6cSJohn Marino   if (current_trace_status ()->running
2466*ef5ccd6cSJohn Marino       && current_trace_status ()->filename == NULL)
2467c50c785cSJohn Marino     error (_("May not look at trace frames while trace is running."));
2468cf7f2e2dSJohn Marino 
24695796c8dcSSimon Schubert   if (args == 0 || *args == 0)
24705796c8dcSSimon Schubert     pc = regcache_read_pc (get_current_regcache ());
24715796c8dcSSimon Schubert   else
24725796c8dcSSimon Schubert     pc = parse_and_eval_address (args);
24735796c8dcSSimon Schubert 
2474cf7f2e2dSJohn Marino   tfind_1 (tfind_pc, 0, pc, 0, from_tty);
24755796c8dcSSimon Schubert }
24765796c8dcSSimon Schubert 
24775796c8dcSSimon Schubert /* tfind tracepoint command */
24785796c8dcSSimon Schubert static void
trace_find_tracepoint_command(char * args,int from_tty)24795796c8dcSSimon Schubert trace_find_tracepoint_command (char *args, int from_tty)
24805796c8dcSSimon Schubert {
24815796c8dcSSimon Schubert   int tdp;
2482a45ae5f8SJohn Marino   struct tracepoint *tp;
24835796c8dcSSimon Schubert 
2484*ef5ccd6cSJohn Marino   if (current_trace_status ()->running
2485*ef5ccd6cSJohn Marino       && current_trace_status ()->filename == NULL)
2486c50c785cSJohn Marino     error (_("May not look at trace frames while trace is running."));
2487cf7f2e2dSJohn Marino 
24885796c8dcSSimon Schubert   if (args == 0 || *args == 0)
24895796c8dcSSimon Schubert     {
24905796c8dcSSimon Schubert       if (tracepoint_number == -1)
24915796c8dcSSimon Schubert 	error (_("No current tracepoint -- please supply an argument."));
24925796c8dcSSimon Schubert       else
2493c50c785cSJohn Marino 	tdp = tracepoint_number;	/* Default is current TDP.  */
24945796c8dcSSimon Schubert     }
24955796c8dcSSimon Schubert   else
24965796c8dcSSimon Schubert     tdp = parse_and_eval_long (args);
24975796c8dcSSimon Schubert 
2498cf7f2e2dSJohn Marino   /* If we have the tracepoint on hand, use the number that the
2499cf7f2e2dSJohn Marino      target knows about (which may be different if we disconnected
2500cf7f2e2dSJohn Marino      and reconnected).  */
2501cf7f2e2dSJohn Marino   tp = get_tracepoint (tdp);
2502cf7f2e2dSJohn Marino   if (tp)
2503cf7f2e2dSJohn Marino     tdp = tp->number_on_target;
2504cf7f2e2dSJohn Marino 
2505cf7f2e2dSJohn Marino   tfind_1 (tfind_tp, tdp, 0, 0, from_tty);
25065796c8dcSSimon Schubert }
25075796c8dcSSimon Schubert 
25085796c8dcSSimon Schubert /* TFIND LINE command:
25095796c8dcSSimon Schubert 
25105796c8dcSSimon Schubert    This command will take a sourceline for argument, just like BREAK
25115796c8dcSSimon Schubert    or TRACE (ie. anything that "decode_line_1" can handle).
25125796c8dcSSimon Schubert 
25135796c8dcSSimon Schubert    With no argument, this command will find the next trace frame
25145796c8dcSSimon Schubert    corresponding to a source line OTHER THAN THE CURRENT ONE.  */
25155796c8dcSSimon Schubert 
25165796c8dcSSimon Schubert static void
trace_find_line_command(char * args,int from_tty)25175796c8dcSSimon Schubert trace_find_line_command (char *args, int from_tty)
25185796c8dcSSimon Schubert {
25195796c8dcSSimon Schubert   static CORE_ADDR start_pc, end_pc;
25205796c8dcSSimon Schubert   struct symtabs_and_lines sals;
25215796c8dcSSimon Schubert   struct symtab_and_line sal;
25225796c8dcSSimon Schubert   struct cleanup *old_chain;
25235796c8dcSSimon Schubert 
2524*ef5ccd6cSJohn Marino   if (current_trace_status ()->running
2525*ef5ccd6cSJohn Marino       && current_trace_status ()->filename == NULL)
2526c50c785cSJohn Marino     error (_("May not look at trace frames while trace is running."));
2527cf7f2e2dSJohn Marino 
25285796c8dcSSimon Schubert   if (args == 0 || *args == 0)
25295796c8dcSSimon Schubert     {
25305796c8dcSSimon Schubert       sal = find_pc_line (get_frame_pc (get_current_frame ()), 0);
25315796c8dcSSimon Schubert       sals.nelts = 1;
25325796c8dcSSimon Schubert       sals.sals = (struct symtab_and_line *)
25335796c8dcSSimon Schubert 	xmalloc (sizeof (struct symtab_and_line));
25345796c8dcSSimon Schubert       sals.sals[0] = sal;
25355796c8dcSSimon Schubert     }
25365796c8dcSSimon Schubert   else
25375796c8dcSSimon Schubert     {
2538*ef5ccd6cSJohn Marino       sals = decode_line_with_current_source (args, DECODE_LINE_FUNFIRSTLINE);
25395796c8dcSSimon Schubert       sal = sals.sals[0];
25405796c8dcSSimon Schubert     }
25415796c8dcSSimon Schubert 
25425796c8dcSSimon Schubert   old_chain = make_cleanup (xfree, sals.sals);
25435796c8dcSSimon Schubert   if (sal.symtab == 0)
2544cf7f2e2dSJohn Marino     error (_("No line number information available."));
25455796c8dcSSimon Schubert 
2546cf7f2e2dSJohn Marino   if (sal.line > 0 && find_line_pc_range (sal, &start_pc, &end_pc))
25475796c8dcSSimon Schubert     {
25485796c8dcSSimon Schubert       if (start_pc == end_pc)
25495796c8dcSSimon Schubert   	{
25505796c8dcSSimon Schubert 	  printf_filtered ("Line %d of \"%s\"",
2551*ef5ccd6cSJohn Marino 			   sal.line,
2552*ef5ccd6cSJohn Marino 			   symtab_to_filename_for_display (sal.symtab));
25535796c8dcSSimon Schubert 	  wrap_here ("  ");
25545796c8dcSSimon Schubert 	  printf_filtered (" is at address ");
2555cf7f2e2dSJohn Marino 	  print_address (get_current_arch (), start_pc, gdb_stdout);
25565796c8dcSSimon Schubert 	  wrap_here ("  ");
25575796c8dcSSimon Schubert 	  printf_filtered (" but contains no code.\n");
25585796c8dcSSimon Schubert 	  sal = find_pc_line (start_pc, 0);
2559cf7f2e2dSJohn Marino 	  if (sal.line > 0
2560cf7f2e2dSJohn Marino 	      && find_line_pc_range (sal, &start_pc, &end_pc)
2561cf7f2e2dSJohn Marino 	      && start_pc != end_pc)
25625796c8dcSSimon Schubert 	    printf_filtered ("Attempting to find line %d instead.\n",
25635796c8dcSSimon Schubert 			     sal.line);
25645796c8dcSSimon Schubert   	  else
25655796c8dcSSimon Schubert 	    error (_("Cannot find a good line."));
25665796c8dcSSimon Schubert   	}
25675796c8dcSSimon Schubert       }
25685796c8dcSSimon Schubert     else
25695796c8dcSSimon Schubert     /* Is there any case in which we get here, and have an address
25705796c8dcSSimon Schubert        which the user would want to see?  If we have debugging
25715796c8dcSSimon Schubert        symbols and no line numbers?  */
25725796c8dcSSimon Schubert     error (_("Line number %d is out of range for \"%s\"."),
2573*ef5ccd6cSJohn Marino 	   sal.line, symtab_to_filename_for_display (sal.symtab));
25745796c8dcSSimon Schubert 
25755796c8dcSSimon Schubert   /* Find within range of stated line.  */
25765796c8dcSSimon Schubert   if (args && *args)
2577cf7f2e2dSJohn Marino     tfind_1 (tfind_range, 0, start_pc, end_pc - 1, from_tty);
25785796c8dcSSimon Schubert   else
2579cf7f2e2dSJohn Marino     tfind_1 (tfind_outside, 0, start_pc, end_pc - 1, from_tty);
25805796c8dcSSimon Schubert   do_cleanups (old_chain);
25815796c8dcSSimon Schubert }
25825796c8dcSSimon Schubert 
25835796c8dcSSimon Schubert /* tfind range command */
25845796c8dcSSimon Schubert static void
trace_find_range_command(char * args,int from_tty)25855796c8dcSSimon Schubert trace_find_range_command (char *args, int from_tty)
25865796c8dcSSimon Schubert {
25875796c8dcSSimon Schubert   static CORE_ADDR start, stop;
25885796c8dcSSimon Schubert   char *tmp;
25895796c8dcSSimon Schubert 
2590*ef5ccd6cSJohn Marino   if (current_trace_status ()->running
2591*ef5ccd6cSJohn Marino       && current_trace_status ()->filename == NULL)
2592c50c785cSJohn Marino     error (_("May not look at trace frames while trace is running."));
2593cf7f2e2dSJohn Marino 
25945796c8dcSSimon Schubert   if (args == 0 || *args == 0)
25955796c8dcSSimon Schubert     { /* XXX FIXME: what should default behavior be?  */
25965796c8dcSSimon Schubert       printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
25975796c8dcSSimon Schubert       return;
25985796c8dcSSimon Schubert     }
25995796c8dcSSimon Schubert 
26005796c8dcSSimon Schubert   if (0 != (tmp = strchr (args, ',')))
26015796c8dcSSimon Schubert     {
2602c50c785cSJohn Marino       *tmp++ = '\0';	/* Terminate start address.  */
2603*ef5ccd6cSJohn Marino       tmp = skip_spaces (tmp);
26045796c8dcSSimon Schubert       start = parse_and_eval_address (args);
26055796c8dcSSimon Schubert       stop = parse_and_eval_address (tmp);
26065796c8dcSSimon Schubert     }
26075796c8dcSSimon Schubert   else
2608c50c785cSJohn Marino     {			/* No explicit end address?  */
26095796c8dcSSimon Schubert       start = parse_and_eval_address (args);
26105796c8dcSSimon Schubert       stop = start + 1;	/* ??? */
26115796c8dcSSimon Schubert     }
26125796c8dcSSimon Schubert 
2613cf7f2e2dSJohn Marino   tfind_1 (tfind_range, 0, start, stop, from_tty);
26145796c8dcSSimon Schubert }
26155796c8dcSSimon Schubert 
26165796c8dcSSimon Schubert /* tfind outside command */
26175796c8dcSSimon Schubert static void
trace_find_outside_command(char * args,int from_tty)26185796c8dcSSimon Schubert trace_find_outside_command (char *args, int from_tty)
26195796c8dcSSimon Schubert {
26205796c8dcSSimon Schubert   CORE_ADDR start, stop;
26215796c8dcSSimon Schubert   char *tmp;
26225796c8dcSSimon Schubert 
2623*ef5ccd6cSJohn Marino   if (current_trace_status ()->running
2624*ef5ccd6cSJohn Marino       && current_trace_status ()->filename == NULL)
2625c50c785cSJohn Marino     error (_("May not look at trace frames while trace is running."));
2626cf7f2e2dSJohn Marino 
26275796c8dcSSimon Schubert   if (args == 0 || *args == 0)
26285796c8dcSSimon Schubert     { /* XXX FIXME: what should default behavior be?  */
26295796c8dcSSimon Schubert       printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
26305796c8dcSSimon Schubert       return;
26315796c8dcSSimon Schubert     }
26325796c8dcSSimon Schubert 
26335796c8dcSSimon Schubert   if (0 != (tmp = strchr (args, ',')))
26345796c8dcSSimon Schubert     {
2635c50c785cSJohn Marino       *tmp++ = '\0';	/* Terminate start address.  */
2636*ef5ccd6cSJohn Marino       tmp = skip_spaces (tmp);
26375796c8dcSSimon Schubert       start = parse_and_eval_address (args);
26385796c8dcSSimon Schubert       stop = parse_and_eval_address (tmp);
26395796c8dcSSimon Schubert     }
26405796c8dcSSimon Schubert   else
2641c50c785cSJohn Marino     {			/* No explicit end address?  */
26425796c8dcSSimon Schubert       start = parse_and_eval_address (args);
26435796c8dcSSimon Schubert       stop = start + 1;	/* ??? */
26445796c8dcSSimon Schubert     }
26455796c8dcSSimon Schubert 
2646cf7f2e2dSJohn Marino   tfind_1 (tfind_outside, 0, start, stop, from_tty);
26475796c8dcSSimon Schubert }
26485796c8dcSSimon Schubert 
26495796c8dcSSimon Schubert /* info scope command: list the locals for a scope.  */
26505796c8dcSSimon Schubert static void
scope_info(char * args,int from_tty)26515796c8dcSSimon Schubert scope_info (char *args, int from_tty)
26525796c8dcSSimon Schubert {
26535796c8dcSSimon Schubert   struct symtabs_and_lines sals;
26545796c8dcSSimon Schubert   struct symbol *sym;
26555796c8dcSSimon Schubert   struct minimal_symbol *msym;
26565796c8dcSSimon Schubert   struct block *block;
2657*ef5ccd6cSJohn Marino   const char *symname;
2658*ef5ccd6cSJohn Marino   char *save_args = args;
2659*ef5ccd6cSJohn Marino   struct block_iterator iter;
26605796c8dcSSimon Schubert   int j, count = 0;
26615796c8dcSSimon Schubert   struct gdbarch *gdbarch;
26625796c8dcSSimon Schubert   int regno;
26635796c8dcSSimon Schubert 
26645796c8dcSSimon Schubert   if (args == 0 || *args == 0)
2665c50c785cSJohn Marino     error (_("requires an argument (function, "
2666c50c785cSJohn Marino 	     "line or *addr) to define a scope"));
26675796c8dcSSimon Schubert 
2668a45ae5f8SJohn Marino   sals = decode_line_1 (&args, DECODE_LINE_FUNFIRSTLINE, NULL, 0);
26695796c8dcSSimon Schubert   if (sals.nelts == 0)
2670c50c785cSJohn Marino     return;		/* Presumably decode_line_1 has already warned.  */
26715796c8dcSSimon Schubert 
2672c50c785cSJohn Marino   /* Resolve line numbers to PC.  */
26735796c8dcSSimon Schubert   resolve_sal_pc (&sals.sals[0]);
26745796c8dcSSimon Schubert   block = block_for_pc (sals.sals[0].pc);
26755796c8dcSSimon Schubert 
26765796c8dcSSimon Schubert   while (block != 0)
26775796c8dcSSimon Schubert     {
2678c50c785cSJohn Marino       QUIT;			/* Allow user to bail out with ^C.  */
26795796c8dcSSimon Schubert       ALL_BLOCK_SYMBOLS (block, iter, sym)
26805796c8dcSSimon Schubert 	{
2681c50c785cSJohn Marino 	  QUIT;			/* Allow user to bail out with ^C.  */
26825796c8dcSSimon Schubert 	  if (count == 0)
26835796c8dcSSimon Schubert 	    printf_filtered ("Scope for %s:\n", save_args);
26845796c8dcSSimon Schubert 	  count++;
26855796c8dcSSimon Schubert 
26865796c8dcSSimon Schubert 	  symname = SYMBOL_PRINT_NAME (sym);
26875796c8dcSSimon Schubert 	  if (symname == NULL || *symname == '\0')
2688c50c785cSJohn Marino 	    continue;		/* Probably botched, certainly useless.  */
26895796c8dcSSimon Schubert 
26905796c8dcSSimon Schubert 	  gdbarch = get_objfile_arch (SYMBOL_SYMTAB (sym)->objfile);
26915796c8dcSSimon Schubert 
26925796c8dcSSimon Schubert 	  printf_filtered ("Symbol %s is ", symname);
26935796c8dcSSimon Schubert 	  switch (SYMBOL_CLASS (sym))
26945796c8dcSSimon Schubert 	    {
26955796c8dcSSimon Schubert 	    default:
2696c50c785cSJohn Marino 	    case LOC_UNDEF:	/* Messed up symbol?  */
26975796c8dcSSimon Schubert 	      printf_filtered ("a bogus symbol, class %d.\n",
26985796c8dcSSimon Schubert 			       SYMBOL_CLASS (sym));
2699c50c785cSJohn Marino 	      count--;		/* Don't count this one.  */
27005796c8dcSSimon Schubert 	      continue;
27015796c8dcSSimon Schubert 	    case LOC_CONST:
2702*ef5ccd6cSJohn Marino 	      printf_filtered ("a constant with value %s (%s)",
2703*ef5ccd6cSJohn Marino 			       plongest (SYMBOL_VALUE (sym)),
2704*ef5ccd6cSJohn Marino 			       hex_string (SYMBOL_VALUE (sym)));
27055796c8dcSSimon Schubert 	      break;
27065796c8dcSSimon Schubert 	    case LOC_CONST_BYTES:
27075796c8dcSSimon Schubert 	      printf_filtered ("constant bytes: ");
27085796c8dcSSimon Schubert 	      if (SYMBOL_TYPE (sym))
27095796c8dcSSimon Schubert 		for (j = 0; j < TYPE_LENGTH (SYMBOL_TYPE (sym)); j++)
27105796c8dcSSimon Schubert 		  fprintf_filtered (gdb_stdout, " %02x",
27115796c8dcSSimon Schubert 				    (unsigned) SYMBOL_VALUE_BYTES (sym)[j]);
27125796c8dcSSimon Schubert 	      break;
27135796c8dcSSimon Schubert 	    case LOC_STATIC:
27145796c8dcSSimon Schubert 	      printf_filtered ("in static storage at address ");
27155796c8dcSSimon Schubert 	      printf_filtered ("%s", paddress (gdbarch,
27165796c8dcSSimon Schubert 					       SYMBOL_VALUE_ADDRESS (sym)));
27175796c8dcSSimon Schubert 	      break;
27185796c8dcSSimon Schubert 	    case LOC_REGISTER:
27195796c8dcSSimon Schubert 	      /* GDBARCH is the architecture associated with the objfile
27205796c8dcSSimon Schubert 		 the symbol is defined in; the target architecture may be
27215796c8dcSSimon Schubert 		 different, and may provide additional registers.  However,
27225796c8dcSSimon Schubert 		 we do not know the target architecture at this point.
27235796c8dcSSimon Schubert 		 We assume the objfile architecture will contain all the
27245796c8dcSSimon Schubert 		 standard registers that occur in debug info in that
27255796c8dcSSimon Schubert 		 objfile.  */
2726c50c785cSJohn Marino 	      regno = SYMBOL_REGISTER_OPS (sym)->register_number (sym,
2727c50c785cSJohn Marino 								  gdbarch);
27285796c8dcSSimon Schubert 
27295796c8dcSSimon Schubert 	      if (SYMBOL_IS_ARGUMENT (sym))
27305796c8dcSSimon Schubert 		printf_filtered ("an argument in register $%s",
27315796c8dcSSimon Schubert 				 gdbarch_register_name (gdbarch, regno));
27325796c8dcSSimon Schubert 	      else
27335796c8dcSSimon Schubert 		printf_filtered ("a local variable in register $%s",
27345796c8dcSSimon Schubert 				 gdbarch_register_name (gdbarch, regno));
27355796c8dcSSimon Schubert 	      break;
27365796c8dcSSimon Schubert 	    case LOC_ARG:
2737*ef5ccd6cSJohn Marino 	      printf_filtered ("an argument at stack/frame offset %s",
2738*ef5ccd6cSJohn Marino 			       plongest (SYMBOL_VALUE (sym)));
27395796c8dcSSimon Schubert 	      break;
27405796c8dcSSimon Schubert 	    case LOC_LOCAL:
2741*ef5ccd6cSJohn Marino 	      printf_filtered ("a local variable at frame offset %s",
2742*ef5ccd6cSJohn Marino 			       plongest (SYMBOL_VALUE (sym)));
27435796c8dcSSimon Schubert 	      break;
27445796c8dcSSimon Schubert 	    case LOC_REF_ARG:
2745*ef5ccd6cSJohn Marino 	      printf_filtered ("a reference argument at offset %s",
2746*ef5ccd6cSJohn Marino 			       plongest (SYMBOL_VALUE (sym)));
27475796c8dcSSimon Schubert 	      break;
27485796c8dcSSimon Schubert 	    case LOC_REGPARM_ADDR:
27495796c8dcSSimon Schubert 	      /* Note comment at LOC_REGISTER.  */
2750c50c785cSJohn Marino 	      regno = SYMBOL_REGISTER_OPS (sym)->register_number (sym,
2751c50c785cSJohn Marino 								  gdbarch);
27525796c8dcSSimon Schubert 	      printf_filtered ("the address of an argument, in register $%s",
27535796c8dcSSimon Schubert 			       gdbarch_register_name (gdbarch, regno));
27545796c8dcSSimon Schubert 	      break;
27555796c8dcSSimon Schubert 	    case LOC_TYPEDEF:
27565796c8dcSSimon Schubert 	      printf_filtered ("a typedef.\n");
27575796c8dcSSimon Schubert 	      continue;
27585796c8dcSSimon Schubert 	    case LOC_LABEL:
27595796c8dcSSimon Schubert 	      printf_filtered ("a label at address ");
27605796c8dcSSimon Schubert 	      printf_filtered ("%s", paddress (gdbarch,
27615796c8dcSSimon Schubert 					       SYMBOL_VALUE_ADDRESS (sym)));
27625796c8dcSSimon Schubert 	      break;
27635796c8dcSSimon Schubert 	    case LOC_BLOCK:
27645796c8dcSSimon Schubert 	      printf_filtered ("a function at address ");
27655796c8dcSSimon Schubert 	      printf_filtered ("%s",
27665796c8dcSSimon Schubert 		paddress (gdbarch, BLOCK_START (SYMBOL_BLOCK_VALUE (sym))));
27675796c8dcSSimon Schubert 	      break;
27685796c8dcSSimon Schubert 	    case LOC_UNRESOLVED:
27695796c8dcSSimon Schubert 	      msym = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (sym),
27705796c8dcSSimon Schubert 					    NULL, NULL);
27715796c8dcSSimon Schubert 	      if (msym == NULL)
27725796c8dcSSimon Schubert 		printf_filtered ("Unresolved Static");
27735796c8dcSSimon Schubert 	      else
27745796c8dcSSimon Schubert 		{
27755796c8dcSSimon Schubert 		  printf_filtered ("static storage at address ");
27765796c8dcSSimon Schubert 		  printf_filtered ("%s",
27775796c8dcSSimon Schubert 		    paddress (gdbarch, SYMBOL_VALUE_ADDRESS (msym)));
27785796c8dcSSimon Schubert 		}
27795796c8dcSSimon Schubert 	      break;
27805796c8dcSSimon Schubert 	    case LOC_OPTIMIZED_OUT:
27815796c8dcSSimon Schubert 	      printf_filtered ("optimized out.\n");
27825796c8dcSSimon Schubert 	      continue;
27835796c8dcSSimon Schubert 	    case LOC_COMPUTED:
2784cf7f2e2dSJohn Marino 	      SYMBOL_COMPUTED_OPS (sym)->describe_location (sym,
2785cf7f2e2dSJohn Marino 							    BLOCK_START (block),
2786cf7f2e2dSJohn Marino 							    gdb_stdout);
27875796c8dcSSimon Schubert 	      break;
27885796c8dcSSimon Schubert 	    }
27895796c8dcSSimon Schubert 	  if (SYMBOL_TYPE (sym))
27905796c8dcSSimon Schubert 	    printf_filtered (", length %d.\n",
27915796c8dcSSimon Schubert 			     TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
27925796c8dcSSimon Schubert 	}
27935796c8dcSSimon Schubert       if (BLOCK_FUNCTION (block))
27945796c8dcSSimon Schubert 	break;
27955796c8dcSSimon Schubert       else
27965796c8dcSSimon Schubert 	block = BLOCK_SUPERBLOCK (block);
27975796c8dcSSimon Schubert     }
27985796c8dcSSimon Schubert   if (count <= 0)
27995796c8dcSSimon Schubert     printf_filtered ("Scope for %s contains no locals or arguments.\n",
28005796c8dcSSimon Schubert 		     save_args);
28015796c8dcSSimon Schubert }
28025796c8dcSSimon Schubert 
28035796c8dcSSimon Schubert /* worker function (cleanup) */
28045796c8dcSSimon Schubert static void
replace_comma(void * data)28055796c8dcSSimon Schubert replace_comma (void *data)
28065796c8dcSSimon Schubert {
28075796c8dcSSimon Schubert   char *comma = data;
28085796c8dcSSimon Schubert   *comma = ',';
28095796c8dcSSimon Schubert }
28105796c8dcSSimon Schubert 
2811cf7f2e2dSJohn Marino 
2812cf7f2e2dSJohn Marino /* Helper for trace_dump_command.  Dump the action list starting at
2813cf7f2e2dSJohn Marino    ACTION.  STEPPING_ACTIONS is true if we're iterating over the
2814cf7f2e2dSJohn Marino    actions of the body of a while-stepping action.  STEPPING_FRAME is
2815cf7f2e2dSJohn Marino    set if the current traceframe was determined to be a while-stepping
2816cf7f2e2dSJohn Marino    traceframe.  */
2817cf7f2e2dSJohn Marino 
28185796c8dcSSimon Schubert static void
trace_dump_actions(struct command_line * action,int stepping_actions,int stepping_frame,int from_tty)2819cf7f2e2dSJohn Marino trace_dump_actions (struct command_line *action,
2820cf7f2e2dSJohn Marino 		    int stepping_actions, int stepping_frame,
2821cf7f2e2dSJohn Marino 		    int from_tty)
28225796c8dcSSimon Schubert {
28235796c8dcSSimon Schubert   char *action_exp, *next_comma;
28245796c8dcSSimon Schubert 
2825cf7f2e2dSJohn Marino   for (; action != NULL; action = action->next)
28265796c8dcSSimon Schubert     {
28275796c8dcSSimon Schubert       struct cmd_list_element *cmd;
28285796c8dcSSimon Schubert 
2829c50c785cSJohn Marino       QUIT;			/* Allow user to bail out with ^C.  */
2830cf7f2e2dSJohn Marino       action_exp = action->line;
2831*ef5ccd6cSJohn Marino       action_exp = skip_spaces (action_exp);
28325796c8dcSSimon Schubert 
28335796c8dcSSimon Schubert       /* The collection actions to be done while stepping are
28345796c8dcSSimon Schubert          bracketed by the commands "while-stepping" and "end".  */
28355796c8dcSSimon Schubert 
28365796c8dcSSimon Schubert       if (*action_exp == '#')	/* comment line */
28375796c8dcSSimon Schubert 	continue;
28385796c8dcSSimon Schubert 
28395796c8dcSSimon Schubert       cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
28405796c8dcSSimon Schubert       if (cmd == 0)
28415796c8dcSSimon Schubert 	error (_("Bad action list item: %s"), action_exp);
28425796c8dcSSimon Schubert 
28435796c8dcSSimon Schubert       if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
2844cf7f2e2dSJohn Marino 	{
2845cf7f2e2dSJohn Marino 	  int i;
2846cf7f2e2dSJohn Marino 
2847cf7f2e2dSJohn Marino 	  for (i = 0; i < action->body_count; ++i)
2848cf7f2e2dSJohn Marino 	    trace_dump_actions (action->body_list[i],
2849cf7f2e2dSJohn Marino 				1, stepping_frame, from_tty);
2850cf7f2e2dSJohn Marino 	}
28515796c8dcSSimon Schubert       else if (cmd_cfunc_eq (cmd, collect_pseudocommand))
28525796c8dcSSimon Schubert 	{
28535796c8dcSSimon Schubert 	  /* Display the collected data.
28545796c8dcSSimon Schubert 	     For the trap frame, display only what was collected at
28555796c8dcSSimon Schubert 	     the trap.  Likewise for stepping frames, display only
28565796c8dcSSimon Schubert 	     what was collected while stepping.  This means that the
28575796c8dcSSimon Schubert 	     two boolean variables, STEPPING_FRAME and
28585796c8dcSSimon Schubert 	     STEPPING_ACTIONS should be equal.  */
28595796c8dcSSimon Schubert 	  if (stepping_frame == stepping_actions)
28605796c8dcSSimon Schubert 	    {
2861a45ae5f8SJohn Marino 	      if (*action_exp == '/')
2862a45ae5f8SJohn Marino 		action_exp = decode_agent_options (action_exp);
2863a45ae5f8SJohn Marino 
28645796c8dcSSimon Schubert 	      do
2865c50c785cSJohn Marino 		{		/* Repeat over a comma-separated list.  */
2866c50c785cSJohn Marino 		  QUIT;		/* Allow user to bail out with ^C.  */
28675796c8dcSSimon Schubert 		  if (*action_exp == ',')
28685796c8dcSSimon Schubert 		    action_exp++;
2869*ef5ccd6cSJohn Marino 		  action_exp = skip_spaces (action_exp);
28705796c8dcSSimon Schubert 
28715796c8dcSSimon Schubert 		  next_comma = strchr (action_exp, ',');
28725796c8dcSSimon Schubert 
28735796c8dcSSimon Schubert 		  if (0 == strncasecmp (action_exp, "$reg", 4))
28745796c8dcSSimon Schubert 		    registers_info (NULL, from_tty);
2875a45ae5f8SJohn Marino 		  else if (0 == strncasecmp (action_exp, "$_ret", 5))
2876a45ae5f8SJohn Marino 		    ;
28775796c8dcSSimon Schubert 		  else if (0 == strncasecmp (action_exp, "$loc", 4))
28785796c8dcSSimon Schubert 		    locals_info (NULL, from_tty);
28795796c8dcSSimon Schubert 		  else if (0 == strncasecmp (action_exp, "$arg", 4))
28805796c8dcSSimon Schubert 		    args_info (NULL, from_tty);
28815796c8dcSSimon Schubert 		  else
28825796c8dcSSimon Schubert 		    {		/* variable */
28835796c8dcSSimon Schubert 		      if (next_comma)
28845796c8dcSSimon Schubert 			{
28855796c8dcSSimon Schubert 			  make_cleanup (replace_comma, next_comma);
28865796c8dcSSimon Schubert 			  *next_comma = '\0';
28875796c8dcSSimon Schubert 			}
28885796c8dcSSimon Schubert 		      printf_filtered ("%s = ", action_exp);
28895796c8dcSSimon Schubert 		      output_command (action_exp, from_tty);
28905796c8dcSSimon Schubert 		      printf_filtered ("\n");
28915796c8dcSSimon Schubert 		    }
28925796c8dcSSimon Schubert 		  if (next_comma)
28935796c8dcSSimon Schubert 		    *next_comma = ',';
28945796c8dcSSimon Schubert 		  action_exp = next_comma;
28955796c8dcSSimon Schubert 		}
28965796c8dcSSimon Schubert 	      while (action_exp && *action_exp == ',');
28975796c8dcSSimon Schubert 	    }
28985796c8dcSSimon Schubert 	}
28995796c8dcSSimon Schubert     }
2900cf7f2e2dSJohn Marino }
2901cf7f2e2dSJohn Marino 
2902cf7f2e2dSJohn Marino /* The tdump command.  */
2903cf7f2e2dSJohn Marino 
2904cf7f2e2dSJohn Marino static void
trace_dump_command(char * args,int from_tty)2905cf7f2e2dSJohn Marino trace_dump_command (char *args, int from_tty)
2906cf7f2e2dSJohn Marino {
2907cf7f2e2dSJohn Marino   struct regcache *regcache;
2908a45ae5f8SJohn Marino   struct tracepoint *t;
2909cf7f2e2dSJohn Marino   int stepping_frame = 0;
2910cf7f2e2dSJohn Marino   struct bp_location *loc;
2911cf7f2e2dSJohn Marino   char *line, *default_collect_line = NULL;
2912cf7f2e2dSJohn Marino   struct command_line *actions, *default_collect_action = NULL;
2913cf7f2e2dSJohn Marino   struct cleanup *old_chain = NULL;
2914cf7f2e2dSJohn Marino 
2915cf7f2e2dSJohn Marino   if (tracepoint_number == -1)
2916cf7f2e2dSJohn Marino     {
2917cf7f2e2dSJohn Marino       warning (_("No current trace frame."));
2918cf7f2e2dSJohn Marino       return;
2919cf7f2e2dSJohn Marino     }
2920cf7f2e2dSJohn Marino 
2921cf7f2e2dSJohn Marino   t = get_tracepoint (tracepoint_number);
2922cf7f2e2dSJohn Marino 
2923cf7f2e2dSJohn Marino   if (t == NULL)
2924cf7f2e2dSJohn Marino     error (_("No known tracepoint matches 'current' tracepoint #%d."),
2925cf7f2e2dSJohn Marino 	   tracepoint_number);
2926cf7f2e2dSJohn Marino 
2927cf7f2e2dSJohn Marino   printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
2928cf7f2e2dSJohn Marino 		   tracepoint_number, traceframe_number);
2929cf7f2e2dSJohn Marino 
2930cf7f2e2dSJohn Marino   /* The current frame is a trap frame if the frame PC is equal
2931cf7f2e2dSJohn Marino      to the tracepoint PC.  If not, then the current frame was
2932cf7f2e2dSJohn Marino      collected during single-stepping.  */
2933cf7f2e2dSJohn Marino 
2934cf7f2e2dSJohn Marino   regcache = get_current_regcache ();
2935cf7f2e2dSJohn Marino 
2936cf7f2e2dSJohn Marino   /* If the traceframe's address matches any of the tracepoint's
2937cf7f2e2dSJohn Marino      locations, assume it is a direct hit rather than a while-stepping
2938cf7f2e2dSJohn Marino      frame.  (FIXME this is not reliable, should record each frame's
2939cf7f2e2dSJohn Marino      type.)  */
2940cf7f2e2dSJohn Marino   stepping_frame = 1;
2941a45ae5f8SJohn Marino   for (loc = t->base.loc; loc; loc = loc->next)
2942cf7f2e2dSJohn Marino     if (loc->address == regcache_read_pc (regcache))
2943cf7f2e2dSJohn Marino       stepping_frame = 0;
2944cf7f2e2dSJohn Marino 
2945a45ae5f8SJohn Marino   actions = breakpoint_commands (&t->base);
2946cf7f2e2dSJohn Marino 
2947cf7f2e2dSJohn Marino   /* If there is a default-collect list, make up a collect command,
2948cf7f2e2dSJohn Marino      prepend to the tracepoint's commands, and pass the whole mess to
2949cf7f2e2dSJohn Marino      the trace dump scanner.  We need to validate because
2950cf7f2e2dSJohn Marino      default-collect might have been junked since the trace run.  */
2951cf7f2e2dSJohn Marino   if (*default_collect)
2952cf7f2e2dSJohn Marino     {
2953cf7f2e2dSJohn Marino       default_collect_line = xstrprintf ("collect %s", default_collect);
2954cf7f2e2dSJohn Marino       old_chain = make_cleanup (xfree, default_collect_line);
2955cf7f2e2dSJohn Marino       line = default_collect_line;
2956a45ae5f8SJohn Marino       validate_actionline (&line, &t->base);
2957cf7f2e2dSJohn Marino       default_collect_action = xmalloc (sizeof (struct command_line));
2958cf7f2e2dSJohn Marino       make_cleanup (xfree, default_collect_action);
2959cf7f2e2dSJohn Marino       default_collect_action->next = actions;
2960cf7f2e2dSJohn Marino       default_collect_action->line = line;
2961cf7f2e2dSJohn Marino       actions = default_collect_action;
2962cf7f2e2dSJohn Marino     }
2963cf7f2e2dSJohn Marino 
2964cf7f2e2dSJohn Marino   trace_dump_actions (actions, 0, stepping_frame, from_tty);
2965cf7f2e2dSJohn Marino 
2966cf7f2e2dSJohn Marino   if (*default_collect)
2967cf7f2e2dSJohn Marino     do_cleanups (old_chain);
2968cf7f2e2dSJohn Marino }
2969cf7f2e2dSJohn Marino 
2970cf7f2e2dSJohn Marino /* Encode a piece of a tracepoint's source-level definition in a form
2971cf7f2e2dSJohn Marino    that is suitable for both protocol and saving in files.  */
2972cf7f2e2dSJohn Marino /* This version does not do multiple encodes for long strings; it should
2973cf7f2e2dSJohn Marino    return an offset to the next piece to encode.  FIXME  */
2974cf7f2e2dSJohn Marino 
2975cf7f2e2dSJohn Marino extern int
encode_source_string(int tpnum,ULONGEST addr,char * srctype,char * src,char * buf,int buf_size)2976cf7f2e2dSJohn Marino encode_source_string (int tpnum, ULONGEST addr,
2977cf7f2e2dSJohn Marino 		      char *srctype, char *src, char *buf, int buf_size)
2978cf7f2e2dSJohn Marino {
2979cf7f2e2dSJohn Marino   if (80 + strlen (srctype) > buf_size)
2980cf7f2e2dSJohn Marino     error (_("Buffer too small for source encoding"));
2981cf7f2e2dSJohn Marino   sprintf (buf, "%x:%s:%s:%x:%x:",
2982c50c785cSJohn Marino 	   tpnum, phex_nz (addr, sizeof (addr)),
2983c50c785cSJohn Marino 	   srctype, 0, (int) strlen (src));
2984cf7f2e2dSJohn Marino   if (strlen (buf) + strlen (src) * 2 >= buf_size)
2985cf7f2e2dSJohn Marino     error (_("Source string too long for buffer"));
2986cf7f2e2dSJohn Marino   bin2hex (src, buf + strlen (buf), 0);
2987cf7f2e2dSJohn Marino   return -1;
2988cf7f2e2dSJohn Marino }
2989cf7f2e2dSJohn Marino 
2990cf7f2e2dSJohn Marino extern int trace_regblock_size;
2991cf7f2e2dSJohn Marino 
2992cf7f2e2dSJohn Marino /* Save tracepoint data to file named FILENAME.  If TARGET_DOES_SAVE is
2993cf7f2e2dSJohn Marino    non-zero, the save is performed on the target, otherwise GDB obtains all
2994cf7f2e2dSJohn Marino    trace data and saves it locally.  */
2995cf7f2e2dSJohn Marino 
2996cf7f2e2dSJohn Marino void
trace_save(const char * filename,int target_does_save)2997cf7f2e2dSJohn Marino trace_save (const char *filename, int target_does_save)
2998cf7f2e2dSJohn Marino {
2999cf7f2e2dSJohn Marino   struct cleanup *cleanup;
3000cf7f2e2dSJohn Marino   char *pathname;
3001cf7f2e2dSJohn Marino   struct trace_status *ts = current_trace_status ();
3002cf7f2e2dSJohn Marino   int err, status;
3003cf7f2e2dSJohn Marino   FILE *fp;
3004cf7f2e2dSJohn Marino   struct uploaded_tp *uploaded_tps = NULL, *utp;
3005cf7f2e2dSJohn Marino   struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;
3006cf7f2e2dSJohn Marino   int a;
3007cf7f2e2dSJohn Marino   char *act;
3008cf7f2e2dSJohn Marino   LONGEST gotten = 0;
3009cf7f2e2dSJohn Marino   ULONGEST offset = 0;
3010cf7f2e2dSJohn Marino #define MAX_TRACE_UPLOAD 2000
3011cf7f2e2dSJohn Marino   gdb_byte buf[MAX_TRACE_UPLOAD];
3012cf7f2e2dSJohn Marino   int written;
3013cf7f2e2dSJohn Marino 
3014cf7f2e2dSJohn Marino   /* If the target is to save the data to a file on its own, then just
3015cf7f2e2dSJohn Marino      send the command and be done with it.  */
3016cf7f2e2dSJohn Marino   if (target_does_save)
3017cf7f2e2dSJohn Marino     {
3018cf7f2e2dSJohn Marino       err = target_save_trace_data (filename);
3019cf7f2e2dSJohn Marino       if (err < 0)
3020cf7f2e2dSJohn Marino 	error (_("Target failed to save trace data to '%s'."),
3021cf7f2e2dSJohn Marino 	       filename);
3022cf7f2e2dSJohn Marino       return;
3023cf7f2e2dSJohn Marino     }
3024cf7f2e2dSJohn Marino 
3025cf7f2e2dSJohn Marino   /* Get the trace status first before opening the file, so if the
3026cf7f2e2dSJohn Marino      target is losing, we can get out without touching files.  */
3027cf7f2e2dSJohn Marino   status = target_get_trace_status (ts);
3028cf7f2e2dSJohn Marino 
3029cf7f2e2dSJohn Marino   pathname = tilde_expand (filename);
3030cf7f2e2dSJohn Marino   cleanup = make_cleanup (xfree, pathname);
3031cf7f2e2dSJohn Marino 
3032cf7f2e2dSJohn Marino   fp = fopen (pathname, "wb");
3033cf7f2e2dSJohn Marino   if (!fp)
3034cf7f2e2dSJohn Marino     error (_("Unable to open file '%s' for saving trace data (%s)"),
3035cf7f2e2dSJohn Marino 	   filename, safe_strerror (errno));
3036cf7f2e2dSJohn Marino   make_cleanup_fclose (fp);
3037cf7f2e2dSJohn Marino 
3038cf7f2e2dSJohn Marino   /* Write a file header, with a high-bit-set char to indicate a
3039cf7f2e2dSJohn Marino      binary file, plus a hint as what this file is, and a version
3040cf7f2e2dSJohn Marino      number in case of future needs.  */
3041cf7f2e2dSJohn Marino   written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
3042cf7f2e2dSJohn Marino   if (written < 1)
3043cf7f2e2dSJohn Marino     perror_with_name (pathname);
3044cf7f2e2dSJohn Marino 
3045cf7f2e2dSJohn Marino   /* Write descriptive info.  */
3046cf7f2e2dSJohn Marino 
3047cf7f2e2dSJohn Marino   /* Write out the size of a register block.  */
3048cf7f2e2dSJohn Marino   fprintf (fp, "R %x\n", trace_regblock_size);
3049cf7f2e2dSJohn Marino 
3050cf7f2e2dSJohn Marino   /* Write out status of the tracing run (aka "tstatus" info).  */
3051cf7f2e2dSJohn Marino   fprintf (fp, "status %c;%s",
3052cf7f2e2dSJohn Marino 	   (ts->running ? '1' : '0'), stop_reason_names[ts->stop_reason]);
3053cf7f2e2dSJohn Marino   if (ts->stop_reason == tracepoint_error)
3054cf7f2e2dSJohn Marino     {
3055a45ae5f8SJohn Marino       char *buf = (char *) alloca (strlen (ts->stop_desc) * 2 + 1);
3056cf7f2e2dSJohn Marino 
3057a45ae5f8SJohn Marino       bin2hex ((gdb_byte *) ts->stop_desc, buf, 0);
3058cf7f2e2dSJohn Marino       fprintf (fp, ":%s", buf);
3059cf7f2e2dSJohn Marino     }
3060cf7f2e2dSJohn Marino   fprintf (fp, ":%x", ts->stopping_tracepoint);
3061cf7f2e2dSJohn Marino   if (ts->traceframe_count >= 0)
3062cf7f2e2dSJohn Marino     fprintf (fp, ";tframes:%x", ts->traceframe_count);
3063cf7f2e2dSJohn Marino   if (ts->traceframes_created >= 0)
3064cf7f2e2dSJohn Marino     fprintf (fp, ";tcreated:%x", ts->traceframes_created);
3065cf7f2e2dSJohn Marino   if (ts->buffer_free >= 0)
3066cf7f2e2dSJohn Marino     fprintf (fp, ";tfree:%x", ts->buffer_free);
3067cf7f2e2dSJohn Marino   if (ts->buffer_size >= 0)
3068cf7f2e2dSJohn Marino     fprintf (fp, ";tsize:%x", ts->buffer_size);
3069cf7f2e2dSJohn Marino   if (ts->disconnected_tracing)
3070cf7f2e2dSJohn Marino     fprintf (fp, ";disconn:%x", ts->disconnected_tracing);
3071cf7f2e2dSJohn Marino   if (ts->circular_buffer)
3072cf7f2e2dSJohn Marino     fprintf (fp, ";circular:%x", ts->circular_buffer);
3073cf7f2e2dSJohn Marino   fprintf (fp, "\n");
3074cf7f2e2dSJohn Marino 
3075cf7f2e2dSJohn Marino   /* Note that we want to upload tracepoints and save those, rather
3076cf7f2e2dSJohn Marino      than simply writing out the local ones, because the user may have
3077cf7f2e2dSJohn Marino      changed tracepoints in GDB in preparation for a future tracing
3078cf7f2e2dSJohn Marino      run, or maybe just mass-deleted all types of breakpoints as part
3079cf7f2e2dSJohn Marino      of cleaning up.  So as not to contaminate the session, leave the
3080cf7f2e2dSJohn Marino      data in its uploaded form, don't make into real tracepoints.  */
3081cf7f2e2dSJohn Marino 
3082cf7f2e2dSJohn Marino   /* Get trace state variables first, they may be checked when parsing
3083cf7f2e2dSJohn Marino      uploaded commands.  */
3084cf7f2e2dSJohn Marino 
3085cf7f2e2dSJohn Marino   target_upload_trace_state_variables (&uploaded_tsvs);
3086cf7f2e2dSJohn Marino 
3087cf7f2e2dSJohn Marino   for (utsv = uploaded_tsvs; utsv; utsv = utsv->next)
3088cf7f2e2dSJohn Marino     {
3089cf7f2e2dSJohn Marino       char *buf = "";
3090cf7f2e2dSJohn Marino 
3091cf7f2e2dSJohn Marino       if (utsv->name)
3092cf7f2e2dSJohn Marino 	{
3093cf7f2e2dSJohn Marino 	  buf = (char *) xmalloc (strlen (utsv->name) * 2 + 1);
3094cf7f2e2dSJohn Marino 	  bin2hex ((gdb_byte *) (utsv->name), buf, 0);
3095cf7f2e2dSJohn Marino 	}
3096cf7f2e2dSJohn Marino 
3097cf7f2e2dSJohn Marino       fprintf (fp, "tsv %x:%s:%x:%s\n",
3098cf7f2e2dSJohn Marino 	       utsv->number, phex_nz (utsv->initial_value, 8),
3099cf7f2e2dSJohn Marino 	       utsv->builtin, buf);
3100cf7f2e2dSJohn Marino 
3101cf7f2e2dSJohn Marino       if (utsv->name)
3102cf7f2e2dSJohn Marino 	xfree (buf);
3103cf7f2e2dSJohn Marino     }
3104cf7f2e2dSJohn Marino 
3105cf7f2e2dSJohn Marino   free_uploaded_tsvs (&uploaded_tsvs);
3106cf7f2e2dSJohn Marino 
3107cf7f2e2dSJohn Marino   target_upload_tracepoints (&uploaded_tps);
3108cf7f2e2dSJohn Marino 
3109cf7f2e2dSJohn Marino   for (utp = uploaded_tps; utp; utp = utp->next)
3110a45ae5f8SJohn Marino     target_get_tracepoint_status (NULL, utp);
3111a45ae5f8SJohn Marino 
3112a45ae5f8SJohn Marino   for (utp = uploaded_tps; utp; utp = utp->next)
3113cf7f2e2dSJohn Marino     {
3114cf7f2e2dSJohn Marino       fprintf (fp, "tp T%x:%s:%c:%x:%x",
3115cf7f2e2dSJohn Marino 	       utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
3116cf7f2e2dSJohn Marino 	       (utp->enabled ? 'E' : 'D'), utp->step, utp->pass);
3117cf7f2e2dSJohn Marino       if (utp->type == bp_fast_tracepoint)
3118cf7f2e2dSJohn Marino 	fprintf (fp, ":F%x", utp->orig_size);
3119cf7f2e2dSJohn Marino       if (utp->cond)
3120cf7f2e2dSJohn Marino 	fprintf (fp, ":X%x,%s", (unsigned int) strlen (utp->cond) / 2,
3121cf7f2e2dSJohn Marino 		 utp->cond);
3122cf7f2e2dSJohn Marino       fprintf (fp, "\n");
3123cf7f2e2dSJohn Marino       for (a = 0; VEC_iterate (char_ptr, utp->actions, a, act); ++a)
3124cf7f2e2dSJohn Marino 	fprintf (fp, "tp A%x:%s:%s\n",
3125cf7f2e2dSJohn Marino 		 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act);
3126c50c785cSJohn Marino       for (a = 0; VEC_iterate (char_ptr, utp->step_actions, a, act); ++a)
3127cf7f2e2dSJohn Marino 	fprintf (fp, "tp S%x:%s:%s\n",
3128cf7f2e2dSJohn Marino 		 utp->number, phex_nz (utp->addr, sizeof (utp->addr)), act);
3129cf7f2e2dSJohn Marino       if (utp->at_string)
3130cf7f2e2dSJohn Marino 	{
3131cf7f2e2dSJohn Marino 	  encode_source_string (utp->number, utp->addr,
3132cf7f2e2dSJohn Marino 				"at", utp->at_string, buf, MAX_TRACE_UPLOAD);
3133cf7f2e2dSJohn Marino 	  fprintf (fp, "tp Z%s\n", buf);
3134cf7f2e2dSJohn Marino 	}
3135cf7f2e2dSJohn Marino       if (utp->cond_string)
3136cf7f2e2dSJohn Marino 	{
3137cf7f2e2dSJohn Marino 	  encode_source_string (utp->number, utp->addr,
3138c50c785cSJohn Marino 				"cond", utp->cond_string,
3139c50c785cSJohn Marino 				buf, MAX_TRACE_UPLOAD);
3140cf7f2e2dSJohn Marino 	  fprintf (fp, "tp Z%s\n", buf);
3141cf7f2e2dSJohn Marino 	}
3142cf7f2e2dSJohn Marino       for (a = 0; VEC_iterate (char_ptr, utp->cmd_strings, a, act); ++a)
3143cf7f2e2dSJohn Marino 	{
3144cf7f2e2dSJohn Marino 	  encode_source_string (utp->number, utp->addr, "cmd", act,
3145cf7f2e2dSJohn Marino 				buf, MAX_TRACE_UPLOAD);
3146cf7f2e2dSJohn Marino 	  fprintf (fp, "tp Z%s\n", buf);
3147cf7f2e2dSJohn Marino 	}
3148a45ae5f8SJohn Marino       fprintf (fp, "tp V%x:%s:%x:%s\n",
3149a45ae5f8SJohn Marino 	       utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
3150a45ae5f8SJohn Marino 	       utp->hit_count,
3151a45ae5f8SJohn Marino 	       phex_nz (utp->traceframe_usage,
3152a45ae5f8SJohn Marino 			sizeof (utp->traceframe_usage)));
3153cf7f2e2dSJohn Marino     }
3154cf7f2e2dSJohn Marino 
3155cf7f2e2dSJohn Marino   free_uploaded_tps (&uploaded_tps);
3156cf7f2e2dSJohn Marino 
3157cf7f2e2dSJohn Marino   /* Mark the end of the definition section.  */
3158cf7f2e2dSJohn Marino   fprintf (fp, "\n");
3159cf7f2e2dSJohn Marino 
3160cf7f2e2dSJohn Marino   /* Get and write the trace data proper.  We ask for big blocks, in
3161cf7f2e2dSJohn Marino      the hopes of efficiency, but will take less if the target has
3162cf7f2e2dSJohn Marino      packet size limitations or some such.  */
3163cf7f2e2dSJohn Marino   while (1)
3164cf7f2e2dSJohn Marino     {
3165cf7f2e2dSJohn Marino       gotten = target_get_raw_trace_data (buf, offset, MAX_TRACE_UPLOAD);
3166cf7f2e2dSJohn Marino       if (gotten < 0)
3167cf7f2e2dSJohn Marino 	error (_("Failure to get requested trace buffer data"));
3168cf7f2e2dSJohn Marino       /* No more data is forthcoming, we're done.  */
3169cf7f2e2dSJohn Marino       if (gotten == 0)
3170cf7f2e2dSJohn Marino 	break;
3171cf7f2e2dSJohn Marino       written = fwrite (buf, gotten, 1, fp);
3172cf7f2e2dSJohn Marino       if (written < 1)
3173cf7f2e2dSJohn Marino 	perror_with_name (pathname);
3174cf7f2e2dSJohn Marino       offset += gotten;
3175cf7f2e2dSJohn Marino     }
3176cf7f2e2dSJohn Marino 
3177cf7f2e2dSJohn Marino   /* Mark the end of trace data.  (We know that gotten is 0 at this point.)  */
3178cf7f2e2dSJohn Marino   written = fwrite (&gotten, 4, 1, fp);
3179cf7f2e2dSJohn Marino   if (written < 1)
3180cf7f2e2dSJohn Marino     perror_with_name (pathname);
3181cf7f2e2dSJohn Marino 
3182cf7f2e2dSJohn Marino   do_cleanups (cleanup);
3183cf7f2e2dSJohn Marino }
3184cf7f2e2dSJohn Marino 
3185cf7f2e2dSJohn Marino static void
trace_save_command(char * args,int from_tty)3186cf7f2e2dSJohn Marino trace_save_command (char *args, int from_tty)
3187cf7f2e2dSJohn Marino {
3188cf7f2e2dSJohn Marino   int target_does_save = 0;
3189cf7f2e2dSJohn Marino   char **argv;
3190cf7f2e2dSJohn Marino   char *filename = NULL;
3191cf7f2e2dSJohn Marino   struct cleanup *back_to;
3192cf7f2e2dSJohn Marino 
3193cf7f2e2dSJohn Marino   if (args == NULL)
3194cf7f2e2dSJohn Marino     error_no_arg (_("file in which to save trace data"));
3195cf7f2e2dSJohn Marino 
3196cf7f2e2dSJohn Marino   argv = gdb_buildargv (args);
3197cf7f2e2dSJohn Marino   back_to = make_cleanup_freeargv (argv);
3198cf7f2e2dSJohn Marino 
3199cf7f2e2dSJohn Marino   for (; *argv; ++argv)
3200cf7f2e2dSJohn Marino     {
3201cf7f2e2dSJohn Marino       if (strcmp (*argv, "-r") == 0)
3202cf7f2e2dSJohn Marino 	target_does_save = 1;
3203cf7f2e2dSJohn Marino       else if (**argv == '-')
3204cf7f2e2dSJohn Marino 	error (_("unknown option `%s'"), *argv);
3205cf7f2e2dSJohn Marino       else
3206cf7f2e2dSJohn Marino 	filename = *argv;
3207cf7f2e2dSJohn Marino     }
3208cf7f2e2dSJohn Marino 
3209cf7f2e2dSJohn Marino   if (!filename)
3210cf7f2e2dSJohn Marino     error_no_arg (_("file in which to save trace data"));
3211cf7f2e2dSJohn Marino 
3212cf7f2e2dSJohn Marino   trace_save (filename, target_does_save);
3213cf7f2e2dSJohn Marino 
3214cf7f2e2dSJohn Marino   if (from_tty)
3215a45ae5f8SJohn Marino     printf_filtered (_("Trace data saved to file '%s'.\n"), filename);
3216cf7f2e2dSJohn Marino 
3217cf7f2e2dSJohn Marino   do_cleanups (back_to);
3218cf7f2e2dSJohn Marino }
3219cf7f2e2dSJohn Marino 
3220cf7f2e2dSJohn Marino /* Tell the target what to do with an ongoing tracing run if GDB
3221cf7f2e2dSJohn Marino    disconnects for some reason.  */
3222cf7f2e2dSJohn Marino 
3223cf7f2e2dSJohn Marino static void
set_disconnected_tracing(char * args,int from_tty,struct cmd_list_element * c)3224cf7f2e2dSJohn Marino set_disconnected_tracing (char *args, int from_tty,
3225cf7f2e2dSJohn Marino 			  struct cmd_list_element *c)
3226cf7f2e2dSJohn Marino {
3227a45ae5f8SJohn Marino   target_set_disconnected_tracing (disconnected_tracing);
3228cf7f2e2dSJohn Marino }
3229cf7f2e2dSJohn Marino 
3230cf7f2e2dSJohn Marino static void
set_circular_trace_buffer(char * args,int from_tty,struct cmd_list_element * c)3231cf7f2e2dSJohn Marino set_circular_trace_buffer (char *args, int from_tty,
3232cf7f2e2dSJohn Marino 			   struct cmd_list_element *c)
3233cf7f2e2dSJohn Marino {
3234cf7f2e2dSJohn Marino   target_set_circular_trace_buffer (circular_trace_buffer);
32355796c8dcSSimon Schubert }
32365796c8dcSSimon Schubert 
3237a45ae5f8SJohn Marino static void
set_trace_buffer_size(char * args,int from_tty,struct cmd_list_element * c)3238*ef5ccd6cSJohn Marino set_trace_buffer_size (char *args, int from_tty,
3239*ef5ccd6cSJohn Marino 			   struct cmd_list_element *c)
3240*ef5ccd6cSJohn Marino {
3241*ef5ccd6cSJohn Marino   target_set_trace_buffer_size (trace_buffer_size);
3242*ef5ccd6cSJohn Marino }
3243*ef5ccd6cSJohn Marino 
3244*ef5ccd6cSJohn Marino static void
set_trace_user(char * args,int from_tty,struct cmd_list_element * c)3245a45ae5f8SJohn Marino set_trace_user (char *args, int from_tty,
3246a45ae5f8SJohn Marino 		struct cmd_list_element *c)
3247a45ae5f8SJohn Marino {
3248a45ae5f8SJohn Marino   int ret;
3249a45ae5f8SJohn Marino 
3250a45ae5f8SJohn Marino   ret = target_set_trace_notes (trace_user, NULL, NULL);
3251a45ae5f8SJohn Marino 
3252a45ae5f8SJohn Marino   if (!ret)
3253*ef5ccd6cSJohn Marino     warning (_("Target does not support trace notes, user ignored"));
3254a45ae5f8SJohn Marino }
3255a45ae5f8SJohn Marino 
3256a45ae5f8SJohn Marino static void
set_trace_notes(char * args,int from_tty,struct cmd_list_element * c)3257a45ae5f8SJohn Marino set_trace_notes (char *args, int from_tty,
3258a45ae5f8SJohn Marino 		 struct cmd_list_element *c)
3259a45ae5f8SJohn Marino {
3260a45ae5f8SJohn Marino   int ret;
3261a45ae5f8SJohn Marino 
3262a45ae5f8SJohn Marino   ret = target_set_trace_notes (NULL, trace_notes, NULL);
3263a45ae5f8SJohn Marino 
3264a45ae5f8SJohn Marino   if (!ret)
3265*ef5ccd6cSJohn Marino     warning (_("Target does not support trace notes, note ignored"));
3266a45ae5f8SJohn Marino }
3267a45ae5f8SJohn Marino 
3268a45ae5f8SJohn Marino static void
set_trace_stop_notes(char * args,int from_tty,struct cmd_list_element * c)3269a45ae5f8SJohn Marino set_trace_stop_notes (char *args, int from_tty,
3270a45ae5f8SJohn Marino 		      struct cmd_list_element *c)
3271a45ae5f8SJohn Marino {
3272a45ae5f8SJohn Marino   int ret;
3273a45ae5f8SJohn Marino 
3274a45ae5f8SJohn Marino   ret = target_set_trace_notes (NULL, NULL, trace_stop_notes);
3275a45ae5f8SJohn Marino 
3276a45ae5f8SJohn Marino   if (!ret)
3277*ef5ccd6cSJohn Marino     warning (_("Target does not support trace notes, stop note ignored"));
3278a45ae5f8SJohn Marino }
3279a45ae5f8SJohn Marino 
32805796c8dcSSimon Schubert /* Convert the memory pointed to by mem into hex, placing result in buf.
32815796c8dcSSimon Schubert  * Return a pointer to the last char put in buf (null)
32825796c8dcSSimon Schubert  * "stolen" from sparc-stub.c
32835796c8dcSSimon Schubert  */
32845796c8dcSSimon Schubert 
32855796c8dcSSimon Schubert static const char hexchars[] = "0123456789abcdef";
32865796c8dcSSimon Schubert 
32875796c8dcSSimon Schubert static char *
mem2hex(gdb_byte * mem,char * buf,int count)32885796c8dcSSimon Schubert mem2hex (gdb_byte *mem, char *buf, int count)
32895796c8dcSSimon Schubert {
32905796c8dcSSimon Schubert   gdb_byte ch;
32915796c8dcSSimon Schubert 
32925796c8dcSSimon Schubert   while (count-- > 0)
32935796c8dcSSimon Schubert     {
32945796c8dcSSimon Schubert       ch = *mem++;
32955796c8dcSSimon Schubert 
32965796c8dcSSimon Schubert       *buf++ = hexchars[ch >> 4];
32975796c8dcSSimon Schubert       *buf++ = hexchars[ch & 0xf];
32985796c8dcSSimon Schubert     }
32995796c8dcSSimon Schubert 
33005796c8dcSSimon Schubert   *buf = 0;
33015796c8dcSSimon Schubert 
33025796c8dcSSimon Schubert   return buf;
33035796c8dcSSimon Schubert }
33045796c8dcSSimon Schubert 
33055796c8dcSSimon Schubert int
get_traceframe_number(void)33065796c8dcSSimon Schubert get_traceframe_number (void)
33075796c8dcSSimon Schubert {
33085796c8dcSSimon Schubert   return traceframe_number;
33095796c8dcSSimon Schubert }
33105796c8dcSSimon Schubert 
3311cf7f2e2dSJohn Marino /* Make the traceframe NUM be the current trace frame.  Does nothing
3312cf7f2e2dSJohn Marino    if NUM is already current.  */
3313cf7f2e2dSJohn Marino 
3314cf7f2e2dSJohn Marino void
set_current_traceframe(int num)3315c50c785cSJohn Marino set_current_traceframe (int num)
3316cf7f2e2dSJohn Marino {
3317cf7f2e2dSJohn Marino   int newnum;
3318cf7f2e2dSJohn Marino 
3319cf7f2e2dSJohn Marino   if (traceframe_number == num)
3320cf7f2e2dSJohn Marino     {
3321cf7f2e2dSJohn Marino       /* Nothing to do.  */
3322cf7f2e2dSJohn Marino       return;
3323cf7f2e2dSJohn Marino     }
3324cf7f2e2dSJohn Marino 
3325cf7f2e2dSJohn Marino   newnum = target_trace_find (tfind_number, num, 0, 0, NULL);
3326cf7f2e2dSJohn Marino 
3327cf7f2e2dSJohn Marino   if (newnum != num)
3328cf7f2e2dSJohn Marino     warning (_("could not change traceframe"));
3329cf7f2e2dSJohn Marino 
3330*ef5ccd6cSJohn Marino   set_traceframe_num (newnum);
3331cf7f2e2dSJohn Marino 
3332cf7f2e2dSJohn Marino   /* Changing the traceframe changes our view of registers and of the
3333cf7f2e2dSJohn Marino      frame chain.  */
3334cf7f2e2dSJohn Marino   registers_changed ();
3335c50c785cSJohn Marino 
3336c50c785cSJohn Marino   clear_traceframe_info ();
3337c50c785cSJohn Marino }
3338c50c785cSJohn Marino 
3339c50c785cSJohn Marino /* Make the traceframe NUM be the current trace frame, and do nothing
3340c50c785cSJohn Marino    more.  */
3341c50c785cSJohn Marino 
3342c50c785cSJohn Marino void
set_traceframe_number(int num)3343c50c785cSJohn Marino set_traceframe_number (int num)
3344c50c785cSJohn Marino {
3345c50c785cSJohn Marino   traceframe_number = num;
3346cf7f2e2dSJohn Marino }
3347cf7f2e2dSJohn Marino 
3348cf7f2e2dSJohn Marino /* A cleanup used when switching away and back from tfind mode.  */
3349cf7f2e2dSJohn Marino 
3350cf7f2e2dSJohn Marino struct current_traceframe_cleanup
3351cf7f2e2dSJohn Marino {
3352cf7f2e2dSJohn Marino   /* The traceframe we were inspecting.  */
3353cf7f2e2dSJohn Marino   int traceframe_number;
3354cf7f2e2dSJohn Marino };
3355cf7f2e2dSJohn Marino 
3356cf7f2e2dSJohn Marino static void
do_restore_current_traceframe_cleanup(void * arg)3357cf7f2e2dSJohn Marino do_restore_current_traceframe_cleanup (void *arg)
3358cf7f2e2dSJohn Marino {
3359cf7f2e2dSJohn Marino   struct current_traceframe_cleanup *old = arg;
3360cf7f2e2dSJohn Marino 
3361c50c785cSJohn Marino   set_current_traceframe (old->traceframe_number);
3362cf7f2e2dSJohn Marino }
3363cf7f2e2dSJohn Marino 
3364cf7f2e2dSJohn Marino static void
restore_current_traceframe_cleanup_dtor(void * arg)3365cf7f2e2dSJohn Marino restore_current_traceframe_cleanup_dtor (void *arg)
3366cf7f2e2dSJohn Marino {
3367cf7f2e2dSJohn Marino   struct current_traceframe_cleanup *old = arg;
3368cf7f2e2dSJohn Marino 
3369cf7f2e2dSJohn Marino   xfree (old);
3370cf7f2e2dSJohn Marino }
3371cf7f2e2dSJohn Marino 
3372cf7f2e2dSJohn Marino struct cleanup *
make_cleanup_restore_current_traceframe(void)3373cf7f2e2dSJohn Marino make_cleanup_restore_current_traceframe (void)
3374cf7f2e2dSJohn Marino {
3375cf7f2e2dSJohn Marino   struct current_traceframe_cleanup *old;
3376cf7f2e2dSJohn Marino 
3377cf7f2e2dSJohn Marino   old = xmalloc (sizeof (struct current_traceframe_cleanup));
3378cf7f2e2dSJohn Marino   old->traceframe_number = traceframe_number;
3379cf7f2e2dSJohn Marino 
3380cf7f2e2dSJohn Marino   return make_cleanup_dtor (do_restore_current_traceframe_cleanup, old,
3381cf7f2e2dSJohn Marino 			    restore_current_traceframe_cleanup_dtor);
3382cf7f2e2dSJohn Marino }
3383cf7f2e2dSJohn Marino 
3384c50c785cSJohn Marino struct cleanup *
make_cleanup_restore_traceframe_number(void)3385c50c785cSJohn Marino make_cleanup_restore_traceframe_number (void)
3386c50c785cSJohn Marino {
3387c50c785cSJohn Marino   return make_cleanup_restore_integer (&traceframe_number);
3388c50c785cSJohn Marino }
3389c50c785cSJohn Marino 
3390cf7f2e2dSJohn Marino /* Given a number and address, return an uploaded tracepoint with that
3391cf7f2e2dSJohn Marino    number, creating if necessary.  */
3392cf7f2e2dSJohn Marino 
3393cf7f2e2dSJohn Marino struct uploaded_tp *
get_uploaded_tp(int num,ULONGEST addr,struct uploaded_tp ** utpp)3394cf7f2e2dSJohn Marino get_uploaded_tp (int num, ULONGEST addr, struct uploaded_tp **utpp)
3395cf7f2e2dSJohn Marino {
3396cf7f2e2dSJohn Marino   struct uploaded_tp *utp;
3397cf7f2e2dSJohn Marino 
3398cf7f2e2dSJohn Marino   for (utp = *utpp; utp; utp = utp->next)
3399cf7f2e2dSJohn Marino     if (utp->number == num && utp->addr == addr)
3400cf7f2e2dSJohn Marino       return utp;
3401cf7f2e2dSJohn Marino   utp = (struct uploaded_tp *) xmalloc (sizeof (struct uploaded_tp));
3402cf7f2e2dSJohn Marino   memset (utp, 0, sizeof (struct uploaded_tp));
3403cf7f2e2dSJohn Marino   utp->number = num;
3404cf7f2e2dSJohn Marino   utp->addr = addr;
3405cf7f2e2dSJohn Marino   utp->actions = NULL;
3406cf7f2e2dSJohn Marino   utp->step_actions = NULL;
3407cf7f2e2dSJohn Marino   utp->cmd_strings = NULL;
3408cf7f2e2dSJohn Marino   utp->next = *utpp;
3409cf7f2e2dSJohn Marino   *utpp = utp;
3410cf7f2e2dSJohn Marino   return utp;
3411cf7f2e2dSJohn Marino }
3412cf7f2e2dSJohn Marino 
3413cf7f2e2dSJohn Marino static void
free_uploaded_tps(struct uploaded_tp ** utpp)3414cf7f2e2dSJohn Marino free_uploaded_tps (struct uploaded_tp **utpp)
3415cf7f2e2dSJohn Marino {
3416cf7f2e2dSJohn Marino   struct uploaded_tp *next_one;
3417cf7f2e2dSJohn Marino 
3418cf7f2e2dSJohn Marino   while (*utpp)
3419cf7f2e2dSJohn Marino     {
3420cf7f2e2dSJohn Marino       next_one = (*utpp)->next;
3421cf7f2e2dSJohn Marino       xfree (*utpp);
3422cf7f2e2dSJohn Marino       *utpp = next_one;
3423cf7f2e2dSJohn Marino     }
3424cf7f2e2dSJohn Marino }
3425cf7f2e2dSJohn Marino 
3426cf7f2e2dSJohn Marino /* Given a number and address, return an uploaded tracepoint with that
3427cf7f2e2dSJohn Marino    number, creating if necessary.  */
3428cf7f2e2dSJohn Marino 
3429*ef5ccd6cSJohn Marino static struct uploaded_tsv *
get_uploaded_tsv(int num,struct uploaded_tsv ** utsvp)3430cf7f2e2dSJohn Marino get_uploaded_tsv (int num, struct uploaded_tsv **utsvp)
3431cf7f2e2dSJohn Marino {
3432cf7f2e2dSJohn Marino   struct uploaded_tsv *utsv;
3433cf7f2e2dSJohn Marino 
3434cf7f2e2dSJohn Marino   for (utsv = *utsvp; utsv; utsv = utsv->next)
3435cf7f2e2dSJohn Marino     if (utsv->number == num)
3436cf7f2e2dSJohn Marino       return utsv;
3437cf7f2e2dSJohn Marino   utsv = (struct uploaded_tsv *) xmalloc (sizeof (struct uploaded_tsv));
3438cf7f2e2dSJohn Marino   memset (utsv, 0, sizeof (struct uploaded_tsv));
3439cf7f2e2dSJohn Marino   utsv->number = num;
3440cf7f2e2dSJohn Marino   utsv->next = *utsvp;
3441cf7f2e2dSJohn Marino   *utsvp = utsv;
3442cf7f2e2dSJohn Marino   return utsv;
3443cf7f2e2dSJohn Marino }
3444cf7f2e2dSJohn Marino 
3445cf7f2e2dSJohn Marino static void
free_uploaded_tsvs(struct uploaded_tsv ** utsvp)3446cf7f2e2dSJohn Marino free_uploaded_tsvs (struct uploaded_tsv **utsvp)
3447cf7f2e2dSJohn Marino {
3448cf7f2e2dSJohn Marino   struct uploaded_tsv *next_one;
3449cf7f2e2dSJohn Marino 
3450cf7f2e2dSJohn Marino   while (*utsvp)
3451cf7f2e2dSJohn Marino     {
3452cf7f2e2dSJohn Marino       next_one = (*utsvp)->next;
3453cf7f2e2dSJohn Marino       xfree (*utsvp);
3454cf7f2e2dSJohn Marino       *utsvp = next_one;
3455cf7f2e2dSJohn Marino     }
3456cf7f2e2dSJohn Marino }
3457cf7f2e2dSJohn Marino 
3458a45ae5f8SJohn Marino /* FIXME this function is heuristic and will miss the cases where the
3459a45ae5f8SJohn Marino    conditional is semantically identical but differs in whitespace,
3460a45ae5f8SJohn Marino    such as "x == 0" vs "x==0".  */
3461a45ae5f8SJohn Marino 
3462a45ae5f8SJohn Marino static int
cond_string_is_same(char * str1,char * str2)3463a45ae5f8SJohn Marino cond_string_is_same (char *str1, char *str2)
3464a45ae5f8SJohn Marino {
3465a45ae5f8SJohn Marino   if (str1 == NULL || str2 == NULL)
3466a45ae5f8SJohn Marino     return (str1 == str2);
3467a45ae5f8SJohn Marino 
3468a45ae5f8SJohn Marino   return (strcmp (str1, str2) == 0);
3469a45ae5f8SJohn Marino }
3470a45ae5f8SJohn Marino 
3471cf7f2e2dSJohn Marino /* Look for an existing tracepoint that seems similar enough to the
3472cf7f2e2dSJohn Marino    uploaded one.  Enablement isn't compared, because the user can
3473cf7f2e2dSJohn Marino    toggle that freely, and may have done so in anticipation of the
3474a45ae5f8SJohn Marino    next trace run.  Return the location of matched tracepoint.  */
3475cf7f2e2dSJohn Marino 
3476*ef5ccd6cSJohn Marino static struct bp_location *
find_matching_tracepoint_location(struct uploaded_tp * utp)3477a45ae5f8SJohn Marino find_matching_tracepoint_location (struct uploaded_tp *utp)
3478cf7f2e2dSJohn Marino {
3479cf7f2e2dSJohn Marino   VEC(breakpoint_p) *tp_vec = all_tracepoints ();
3480cf7f2e2dSJohn Marino   int ix;
3481a45ae5f8SJohn Marino   struct breakpoint *b;
3482cf7f2e2dSJohn Marino   struct bp_location *loc;
3483cf7f2e2dSJohn Marino 
3484a45ae5f8SJohn Marino   for (ix = 0; VEC_iterate (breakpoint_p, tp_vec, ix, b); ix++)
3485cf7f2e2dSJohn Marino     {
3486a45ae5f8SJohn Marino       struct tracepoint *t = (struct tracepoint *) b;
3487a45ae5f8SJohn Marino 
3488a45ae5f8SJohn Marino       if (b->type == utp->type
3489cf7f2e2dSJohn Marino 	  && t->step_count == utp->step
3490cf7f2e2dSJohn Marino 	  && t->pass_count == utp->pass
3491a45ae5f8SJohn Marino 	  && cond_string_is_same (t->base.cond_string, utp->cond_string)
3492a45ae5f8SJohn Marino 	  /* FIXME also test actions.  */
3493cf7f2e2dSJohn Marino 	  )
3494cf7f2e2dSJohn Marino 	{
3495cf7f2e2dSJohn Marino 	  /* Scan the locations for an address match.  */
3496a45ae5f8SJohn Marino 	  for (loc = b->loc; loc; loc = loc->next)
3497cf7f2e2dSJohn Marino 	    {
3498cf7f2e2dSJohn Marino 	      if (loc->address == utp->addr)
3499a45ae5f8SJohn Marino 		return loc;
3500cf7f2e2dSJohn Marino 	    }
3501cf7f2e2dSJohn Marino 	}
3502cf7f2e2dSJohn Marino     }
3503cf7f2e2dSJohn Marino   return NULL;
3504cf7f2e2dSJohn Marino }
3505cf7f2e2dSJohn Marino 
3506cf7f2e2dSJohn Marino /* Given a list of tracepoints uploaded from a target, attempt to
3507cf7f2e2dSJohn Marino    match them up with existing tracepoints, and create new ones if not
3508cf7f2e2dSJohn Marino    found.  */
3509cf7f2e2dSJohn Marino 
3510cf7f2e2dSJohn Marino void
merge_uploaded_tracepoints(struct uploaded_tp ** uploaded_tps)3511cf7f2e2dSJohn Marino merge_uploaded_tracepoints (struct uploaded_tp **uploaded_tps)
3512cf7f2e2dSJohn Marino {
3513cf7f2e2dSJohn Marino   struct uploaded_tp *utp;
3514*ef5ccd6cSJohn Marino   /* A set of tracepoints which are modified.  */
3515*ef5ccd6cSJohn Marino   VEC(breakpoint_p) *modified_tp = NULL;
3516*ef5ccd6cSJohn Marino   int ix;
3517*ef5ccd6cSJohn Marino   struct breakpoint *b;
3518cf7f2e2dSJohn Marino 
3519cf7f2e2dSJohn Marino   /* Look for GDB tracepoints that match up with our uploaded versions.  */
3520cf7f2e2dSJohn Marino   for (utp = *uploaded_tps; utp; utp = utp->next)
3521cf7f2e2dSJohn Marino     {
3522a45ae5f8SJohn Marino       struct bp_location *loc;
3523a45ae5f8SJohn Marino       struct tracepoint *t;
3524a45ae5f8SJohn Marino 
3525a45ae5f8SJohn Marino       loc = find_matching_tracepoint_location (utp);
3526a45ae5f8SJohn Marino       if (loc)
3527a45ae5f8SJohn Marino 	{
3528*ef5ccd6cSJohn Marino 	  int found = 0;
3529*ef5ccd6cSJohn Marino 
3530a45ae5f8SJohn Marino 	  /* Mark this location as already inserted.  */
3531a45ae5f8SJohn Marino 	  loc->inserted = 1;
3532a45ae5f8SJohn Marino 	  t = (struct tracepoint *) loc->owner;
3533c50c785cSJohn Marino 	  printf_filtered (_("Assuming tracepoint %d is same "
3534c50c785cSJohn Marino 			     "as target's tracepoint %d at %s.\n"),
3535a45ae5f8SJohn Marino 			   loc->owner->number, utp->number,
3536a45ae5f8SJohn Marino 			   paddress (loc->gdbarch, utp->addr));
3537*ef5ccd6cSJohn Marino 
3538*ef5ccd6cSJohn Marino 	  /* The tracepoint LOC->owner was modified (the location LOC
3539*ef5ccd6cSJohn Marino 	     was marked as inserted in the target).  Save it in
3540*ef5ccd6cSJohn Marino 	     MODIFIED_TP if not there yet.  The 'breakpoint-modified'
3541*ef5ccd6cSJohn Marino 	     observers will be notified later once for each tracepoint
3542*ef5ccd6cSJohn Marino 	     saved in MODIFIED_TP.  */
3543*ef5ccd6cSJohn Marino 	  for (ix = 0;
3544*ef5ccd6cSJohn Marino 	       VEC_iterate (breakpoint_p, modified_tp, ix, b);
3545*ef5ccd6cSJohn Marino 	       ix++)
3546*ef5ccd6cSJohn Marino 	    if (b == loc->owner)
3547*ef5ccd6cSJohn Marino 	      {
3548*ef5ccd6cSJohn Marino 		found = 1;
3549*ef5ccd6cSJohn Marino 		break;
3550*ef5ccd6cSJohn Marino 	      }
3551*ef5ccd6cSJohn Marino 	  if (!found)
3552*ef5ccd6cSJohn Marino 	    VEC_safe_push (breakpoint_p, modified_tp, loc->owner);
3553a45ae5f8SJohn Marino 	}
3554cf7f2e2dSJohn Marino       else
3555cf7f2e2dSJohn Marino 	{
3556cf7f2e2dSJohn Marino 	  t = create_tracepoint_from_upload (utp);
3557cf7f2e2dSJohn Marino 	  if (t)
3558c50c785cSJohn Marino 	    printf_filtered (_("Created tracepoint %d for "
3559c50c785cSJohn Marino 			       "target's tracepoint %d at %s.\n"),
3560a45ae5f8SJohn Marino 			     t->base.number, utp->number,
3561c50c785cSJohn Marino 			     paddress (get_current_arch (), utp->addr));
3562cf7f2e2dSJohn Marino 	  else
3563c50c785cSJohn Marino 	    printf_filtered (_("Failed to create tracepoint for target's "
3564c50c785cSJohn Marino 			       "tracepoint %d at %s, skipping it.\n"),
3565c50c785cSJohn Marino 			     utp->number,
3566c50c785cSJohn Marino 			     paddress (get_current_arch (), utp->addr));
3567cf7f2e2dSJohn Marino 	}
3568cf7f2e2dSJohn Marino       /* Whether found or created, record the number used by the
3569cf7f2e2dSJohn Marino 	 target, to help with mapping target tracepoints back to their
3570cf7f2e2dSJohn Marino 	 counterparts here.  */
3571cf7f2e2dSJohn Marino       if (t)
3572cf7f2e2dSJohn Marino 	t->number_on_target = utp->number;
3573cf7f2e2dSJohn Marino     }
3574cf7f2e2dSJohn Marino 
3575*ef5ccd6cSJohn Marino   /* Notify 'breakpoint-modified' observer that at least one of B's
3576*ef5ccd6cSJohn Marino      locations was changed.  */
3577*ef5ccd6cSJohn Marino   for (ix = 0; VEC_iterate (breakpoint_p, modified_tp, ix, b); ix++)
3578*ef5ccd6cSJohn Marino     observer_notify_breakpoint_modified (b);
3579*ef5ccd6cSJohn Marino 
3580*ef5ccd6cSJohn Marino   VEC_free (breakpoint_p, modified_tp);
3581cf7f2e2dSJohn Marino   free_uploaded_tps (uploaded_tps);
3582cf7f2e2dSJohn Marino }
3583cf7f2e2dSJohn Marino 
3584cf7f2e2dSJohn Marino /* Trace state variables don't have much to identify them beyond their
3585cf7f2e2dSJohn Marino    name, so just use that to detect matches.  */
3586cf7f2e2dSJohn Marino 
3587*ef5ccd6cSJohn Marino static struct trace_state_variable *
find_matching_tsv(struct uploaded_tsv * utsv)3588cf7f2e2dSJohn Marino find_matching_tsv (struct uploaded_tsv *utsv)
3589cf7f2e2dSJohn Marino {
3590cf7f2e2dSJohn Marino   if (!utsv->name)
3591cf7f2e2dSJohn Marino     return NULL;
3592cf7f2e2dSJohn Marino 
3593cf7f2e2dSJohn Marino   return find_trace_state_variable (utsv->name);
3594cf7f2e2dSJohn Marino }
3595cf7f2e2dSJohn Marino 
3596*ef5ccd6cSJohn Marino static struct trace_state_variable *
create_tsv_from_upload(struct uploaded_tsv * utsv)3597cf7f2e2dSJohn Marino create_tsv_from_upload (struct uploaded_tsv *utsv)
3598cf7f2e2dSJohn Marino {
3599cf7f2e2dSJohn Marino   const char *namebase;
3600a45ae5f8SJohn Marino   char *buf;
3601cf7f2e2dSJohn Marino   int try_num = 0;
3602cf7f2e2dSJohn Marino   struct trace_state_variable *tsv;
3603a45ae5f8SJohn Marino   struct cleanup *old_chain;
3604cf7f2e2dSJohn Marino 
3605cf7f2e2dSJohn Marino   if (utsv->name)
3606cf7f2e2dSJohn Marino     {
3607cf7f2e2dSJohn Marino       namebase = utsv->name;
3608a45ae5f8SJohn Marino       buf = xstrprintf ("%s", namebase);
3609cf7f2e2dSJohn Marino     }
3610cf7f2e2dSJohn Marino   else
3611cf7f2e2dSJohn Marino     {
3612cf7f2e2dSJohn Marino       namebase = "__tsv";
3613a45ae5f8SJohn Marino       buf = xstrprintf ("%s_%d", namebase, try_num++);
3614cf7f2e2dSJohn Marino     }
3615cf7f2e2dSJohn Marino 
3616cf7f2e2dSJohn Marino   /* Fish for a name that is not in use.  */
3617cf7f2e2dSJohn Marino   /* (should check against all internal vars?)  */
3618cf7f2e2dSJohn Marino   while (find_trace_state_variable (buf))
3619a45ae5f8SJohn Marino     {
3620a45ae5f8SJohn Marino       xfree (buf);
3621a45ae5f8SJohn Marino       buf = xstrprintf ("%s_%d", namebase, try_num++);
3622a45ae5f8SJohn Marino     }
3623a45ae5f8SJohn Marino 
3624a45ae5f8SJohn Marino   old_chain = make_cleanup (xfree, buf);
3625cf7f2e2dSJohn Marino 
3626cf7f2e2dSJohn Marino   /* We have an available name, create the variable.  */
3627c50c785cSJohn Marino   tsv = create_trace_state_variable (buf);
3628cf7f2e2dSJohn Marino   tsv->initial_value = utsv->initial_value;
3629cf7f2e2dSJohn Marino   tsv->builtin = utsv->builtin;
3630cf7f2e2dSJohn Marino 
3631*ef5ccd6cSJohn Marino   observer_notify_tsv_created (tsv);
3632*ef5ccd6cSJohn Marino 
3633a45ae5f8SJohn Marino   do_cleanups (old_chain);
3634a45ae5f8SJohn Marino 
3635cf7f2e2dSJohn Marino   return tsv;
3636cf7f2e2dSJohn Marino }
3637cf7f2e2dSJohn Marino 
3638cf7f2e2dSJohn Marino /* Given a list of uploaded trace state variables, try to match them
3639cf7f2e2dSJohn Marino    up with existing variables, or create additional ones.  */
3640cf7f2e2dSJohn Marino 
3641cf7f2e2dSJohn Marino void
merge_uploaded_trace_state_variables(struct uploaded_tsv ** uploaded_tsvs)3642cf7f2e2dSJohn Marino merge_uploaded_trace_state_variables (struct uploaded_tsv **uploaded_tsvs)
3643cf7f2e2dSJohn Marino {
3644cf7f2e2dSJohn Marino   int ix;
3645cf7f2e2dSJohn Marino   struct uploaded_tsv *utsv;
3646cf7f2e2dSJohn Marino   struct trace_state_variable *tsv;
3647cf7f2e2dSJohn Marino   int highest;
3648cf7f2e2dSJohn Marino 
3649cf7f2e2dSJohn Marino   /* Most likely some numbers will have to be reassigned as part of
3650cf7f2e2dSJohn Marino      the merge, so clear them all in anticipation.  */
3651cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
3652cf7f2e2dSJohn Marino     tsv->number = 0;
3653cf7f2e2dSJohn Marino 
3654cf7f2e2dSJohn Marino   for (utsv = *uploaded_tsvs; utsv; utsv = utsv->next)
3655cf7f2e2dSJohn Marino     {
3656cf7f2e2dSJohn Marino       tsv = find_matching_tsv (utsv);
3657cf7f2e2dSJohn Marino       if (tsv)
3658c50c785cSJohn Marino 	{
3659c50c785cSJohn Marino 	  if (info_verbose)
3660c50c785cSJohn Marino 	    printf_filtered (_("Assuming trace state variable $%s "
3661c50c785cSJohn Marino 			       "is same as target's variable %d.\n"),
3662cf7f2e2dSJohn Marino 			     tsv->name, utsv->number);
3663c50c785cSJohn Marino 	}
3664cf7f2e2dSJohn Marino       else
3665cf7f2e2dSJohn Marino 	{
3666cf7f2e2dSJohn Marino 	  tsv = create_tsv_from_upload (utsv);
3667c50c785cSJohn Marino 	  if (info_verbose)
3668c50c785cSJohn Marino 	    printf_filtered (_("Created trace state variable "
3669c50c785cSJohn Marino 			       "$%s for target's variable %d.\n"),
3670cf7f2e2dSJohn Marino 			     tsv->name, utsv->number);
3671cf7f2e2dSJohn Marino 	}
3672cf7f2e2dSJohn Marino       /* Give precedence to numberings that come from the target.  */
3673cf7f2e2dSJohn Marino       if (tsv)
3674cf7f2e2dSJohn Marino 	tsv->number = utsv->number;
3675cf7f2e2dSJohn Marino     }
3676cf7f2e2dSJohn Marino 
3677cf7f2e2dSJohn Marino   /* Renumber everything that didn't get a target-assigned number.  */
3678cf7f2e2dSJohn Marino   highest = 0;
3679cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
3680cf7f2e2dSJohn Marino     if (tsv->number > highest)
3681cf7f2e2dSJohn Marino       highest = tsv->number;
3682cf7f2e2dSJohn Marino 
3683cf7f2e2dSJohn Marino   ++highest;
3684cf7f2e2dSJohn Marino   for (ix = 0; VEC_iterate (tsv_s, tvariables, ix, tsv); ++ix)
3685cf7f2e2dSJohn Marino     if (tsv->number == 0)
3686cf7f2e2dSJohn Marino       tsv->number = highest++;
3687cf7f2e2dSJohn Marino 
3688cf7f2e2dSJohn Marino   free_uploaded_tsvs (uploaded_tsvs);
3689cf7f2e2dSJohn Marino }
3690cf7f2e2dSJohn Marino 
3691cf7f2e2dSJohn Marino /* target tfile command */
3692cf7f2e2dSJohn Marino 
3693*ef5ccd6cSJohn Marino static struct target_ops tfile_ops;
3694cf7f2e2dSJohn Marino 
3695cf7f2e2dSJohn Marino /* Fill in tfile_ops with its defined operations and properties.  */
3696cf7f2e2dSJohn Marino 
3697cf7f2e2dSJohn Marino #define TRACE_HEADER_SIZE 8
3698cf7f2e2dSJohn Marino 
3699*ef5ccd6cSJohn Marino static char *trace_filename;
3700*ef5ccd6cSJohn Marino static int trace_fd = -1;
3701*ef5ccd6cSJohn Marino static off_t trace_frames_offset;
3702*ef5ccd6cSJohn Marino static off_t cur_offset;
3703*ef5ccd6cSJohn Marino static int cur_data_size;
3704cf7f2e2dSJohn Marino int trace_regblock_size;
3705cf7f2e2dSJohn Marino 
3706cf7f2e2dSJohn Marino static void tfile_interp_line (char *line,
3707cf7f2e2dSJohn Marino 			       struct uploaded_tp **utpp,
3708cf7f2e2dSJohn Marino 			       struct uploaded_tsv **utsvp);
3709cf7f2e2dSJohn Marino 
3710c50c785cSJohn Marino /* Read SIZE bytes into READBUF from the trace frame, starting at
3711c50c785cSJohn Marino    TRACE_FD's current position.  Note that this call `read'
3712c50c785cSJohn Marino    underneath, hence it advances the file's seek position.  Throws an
3713c50c785cSJohn Marino    error if the `read' syscall fails, or less than SIZE bytes are
3714c50c785cSJohn Marino    read.  */
3715c50c785cSJohn Marino 
3716c50c785cSJohn Marino static void
tfile_read(gdb_byte * readbuf,int size)3717c50c785cSJohn Marino tfile_read (gdb_byte *readbuf, int size)
3718c50c785cSJohn Marino {
3719c50c785cSJohn Marino   int gotten;
3720c50c785cSJohn Marino 
3721c50c785cSJohn Marino   gotten = read (trace_fd, readbuf, size);
3722c50c785cSJohn Marino   if (gotten < 0)
3723c50c785cSJohn Marino     perror_with_name (trace_filename);
3724c50c785cSJohn Marino   else if (gotten < size)
3725c50c785cSJohn Marino     error (_("Premature end of file while reading trace file"));
3726c50c785cSJohn Marino }
3727c50c785cSJohn Marino 
3728cf7f2e2dSJohn Marino static void
tfile_open(char * filename,int from_tty)3729cf7f2e2dSJohn Marino tfile_open (char *filename, int from_tty)
3730cf7f2e2dSJohn Marino {
3731c50c785cSJohn Marino   volatile struct gdb_exception ex;
3732cf7f2e2dSJohn Marino   char *temp;
3733cf7f2e2dSJohn Marino   struct cleanup *old_chain;
3734cf7f2e2dSJohn Marino   int flags;
3735cf7f2e2dSJohn Marino   int scratch_chan;
3736cf7f2e2dSJohn Marino   char header[TRACE_HEADER_SIZE];
3737c50c785cSJohn Marino   char linebuf[1000]; /* Should be max remote packet size or so.  */
3738cf7f2e2dSJohn Marino   char byte;
3739c50c785cSJohn Marino   int bytes, i;
3740cf7f2e2dSJohn Marino   struct trace_status *ts;
3741cf7f2e2dSJohn Marino   struct uploaded_tp *uploaded_tps = NULL;
3742cf7f2e2dSJohn Marino   struct uploaded_tsv *uploaded_tsvs = NULL;
3743cf7f2e2dSJohn Marino 
3744cf7f2e2dSJohn Marino   target_preopen (from_tty);
3745cf7f2e2dSJohn Marino   if (!filename)
3746cf7f2e2dSJohn Marino     error (_("No trace file specified."));
3747cf7f2e2dSJohn Marino 
3748cf7f2e2dSJohn Marino   filename = tilde_expand (filename);
3749cf7f2e2dSJohn Marino   if (!IS_ABSOLUTE_PATH(filename))
3750cf7f2e2dSJohn Marino     {
3751cf7f2e2dSJohn Marino       temp = concat (current_directory, "/", filename, (char *) NULL);
3752cf7f2e2dSJohn Marino       xfree (filename);
3753cf7f2e2dSJohn Marino       filename = temp;
3754cf7f2e2dSJohn Marino     }
3755cf7f2e2dSJohn Marino 
3756cf7f2e2dSJohn Marino   old_chain = make_cleanup (xfree, filename);
3757cf7f2e2dSJohn Marino 
3758cf7f2e2dSJohn Marino   flags = O_BINARY | O_LARGEFILE;
3759cf7f2e2dSJohn Marino   flags |= O_RDONLY;
3760cf7f2e2dSJohn Marino   scratch_chan = open (filename, flags, 0);
3761cf7f2e2dSJohn Marino   if (scratch_chan < 0)
3762cf7f2e2dSJohn Marino     perror_with_name (filename);
3763cf7f2e2dSJohn Marino 
3764cf7f2e2dSJohn Marino   /* Looks semi-reasonable.  Toss the old trace file and work on the new.  */
3765cf7f2e2dSJohn Marino 
3766c50c785cSJohn Marino   discard_cleanups (old_chain);	/* Don't free filename any more.  */
3767cf7f2e2dSJohn Marino   unpush_target (&tfile_ops);
3768cf7f2e2dSJohn Marino 
3769cf7f2e2dSJohn Marino   trace_filename = xstrdup (filename);
3770cf7f2e2dSJohn Marino   trace_fd = scratch_chan;
3771cf7f2e2dSJohn Marino 
3772cf7f2e2dSJohn Marino   bytes = 0;
3773cf7f2e2dSJohn Marino   /* Read the file header and test for validity.  */
3774c50c785cSJohn Marino   tfile_read ((gdb_byte *) &header, TRACE_HEADER_SIZE);
3775cf7f2e2dSJohn Marino 
3776cf7f2e2dSJohn Marino   bytes += TRACE_HEADER_SIZE;
3777cf7f2e2dSJohn Marino   if (!(header[0] == 0x7f
3778cf7f2e2dSJohn Marino 	&& (strncmp (header + 1, "TRACE0\n", 7) == 0)))
3779cf7f2e2dSJohn Marino     error (_("File is not a valid trace file."));
3780cf7f2e2dSJohn Marino 
3781c50c785cSJohn Marino   push_target (&tfile_ops);
3782c50c785cSJohn Marino 
3783cf7f2e2dSJohn Marino   trace_regblock_size = 0;
3784cf7f2e2dSJohn Marino   ts = current_trace_status ();
3785*ef5ccd6cSJohn Marino   /* We know we're working with a file.  Record its name.  */
3786*ef5ccd6cSJohn Marino   ts->filename = trace_filename;
3787cf7f2e2dSJohn Marino   /* Set defaults in case there is no status line.  */
3788cf7f2e2dSJohn Marino   ts->running_known = 0;
3789cf7f2e2dSJohn Marino   ts->stop_reason = trace_stop_reason_unknown;
3790cf7f2e2dSJohn Marino   ts->traceframe_count = -1;
3791cf7f2e2dSJohn Marino   ts->buffer_free = 0;
3792cf7f2e2dSJohn Marino   ts->disconnected_tracing = 0;
3793cf7f2e2dSJohn Marino   ts->circular_buffer = 0;
3794cf7f2e2dSJohn Marino 
3795c50c785cSJohn Marino   TRY_CATCH (ex, RETURN_MASK_ALL)
3796c50c785cSJohn Marino     {
3797cf7f2e2dSJohn Marino       /* Read through a section of newline-terminated lines that
3798cf7f2e2dSJohn Marino 	 define things like tracepoints.  */
3799cf7f2e2dSJohn Marino       i = 0;
3800cf7f2e2dSJohn Marino       while (1)
3801cf7f2e2dSJohn Marino 	{
3802c50c785cSJohn Marino 	  tfile_read (&byte, 1);
3803cf7f2e2dSJohn Marino 
3804cf7f2e2dSJohn Marino 	  ++bytes;
3805cf7f2e2dSJohn Marino 	  if (byte == '\n')
3806cf7f2e2dSJohn Marino 	    {
3807cf7f2e2dSJohn Marino 	      /* Empty line marks end of the definition section.  */
3808cf7f2e2dSJohn Marino 	      if (i == 0)
3809cf7f2e2dSJohn Marino 		break;
3810cf7f2e2dSJohn Marino 	      linebuf[i] = '\0';
3811cf7f2e2dSJohn Marino 	      i = 0;
3812cf7f2e2dSJohn Marino 	      tfile_interp_line (linebuf, &uploaded_tps, &uploaded_tsvs);
3813cf7f2e2dSJohn Marino 	    }
3814cf7f2e2dSJohn Marino 	  else
3815cf7f2e2dSJohn Marino 	    linebuf[i++] = byte;
3816cf7f2e2dSJohn Marino 	  if (i >= 1000)
3817cf7f2e2dSJohn Marino 	    error (_("Excessively long lines in trace file"));
3818cf7f2e2dSJohn Marino 	}
3819cf7f2e2dSJohn Marino 
3820c50c785cSJohn Marino       /* Record the starting offset of the binary trace data.  */
3821c50c785cSJohn Marino       trace_frames_offset = bytes;
3822c50c785cSJohn Marino 
3823c50c785cSJohn Marino       /* If we don't have a blocksize, we can't interpret the
3824c50c785cSJohn Marino 	 traceframes.  */
3825c50c785cSJohn Marino       if (trace_regblock_size == 0)
3826c50c785cSJohn Marino 	error (_("No register block size recorded in trace file"));
3827c50c785cSJohn Marino     }
3828c50c785cSJohn Marino   if (ex.reason < 0)
3829c50c785cSJohn Marino     {
3830c50c785cSJohn Marino       /* Pop the partially set up target.  */
3831c50c785cSJohn Marino       pop_target ();
3832c50c785cSJohn Marino       throw_exception (ex);
3833c50c785cSJohn Marino     }
3834c50c785cSJohn Marino 
3835c50c785cSJohn Marino   inferior_appeared (current_inferior (), TFILE_PID);
3836c50c785cSJohn Marino   inferior_ptid = pid_to_ptid (TFILE_PID);
3837c50c785cSJohn Marino   add_thread_silent (inferior_ptid);
3838c50c785cSJohn Marino 
3839c50c785cSJohn Marino   if (ts->traceframe_count <= 0)
3840c50c785cSJohn Marino     warning (_("No traceframes present in this file."));
3841c50c785cSJohn Marino 
3842cf7f2e2dSJohn Marino   /* Add the file's tracepoints and variables into the current mix.  */
3843cf7f2e2dSJohn Marino 
3844cf7f2e2dSJohn Marino   /* Get trace state variables first, they may be checked when parsing
3845cf7f2e2dSJohn Marino      uploaded commands.  */
3846cf7f2e2dSJohn Marino   merge_uploaded_trace_state_variables (&uploaded_tsvs);
3847cf7f2e2dSJohn Marino 
3848cf7f2e2dSJohn Marino   merge_uploaded_tracepoints (&uploaded_tps);
3849cf7f2e2dSJohn Marino 
3850cf7f2e2dSJohn Marino   post_create_inferior (&tfile_ops, from_tty);
3851cf7f2e2dSJohn Marino }
3852cf7f2e2dSJohn Marino 
3853cf7f2e2dSJohn Marino /* Interpret the given line from the definitions part of the trace
3854cf7f2e2dSJohn Marino    file.  */
3855cf7f2e2dSJohn Marino 
3856cf7f2e2dSJohn Marino static void
tfile_interp_line(char * line,struct uploaded_tp ** utpp,struct uploaded_tsv ** utsvp)3857cf7f2e2dSJohn Marino tfile_interp_line (char *line,
3858cf7f2e2dSJohn Marino 		   struct uploaded_tp **utpp, struct uploaded_tsv **utsvp)
3859cf7f2e2dSJohn Marino {
3860cf7f2e2dSJohn Marino   char *p = line;
3861cf7f2e2dSJohn Marino 
3862cf7f2e2dSJohn Marino   if (strncmp (p, "R ", strlen ("R ")) == 0)
3863cf7f2e2dSJohn Marino     {
3864cf7f2e2dSJohn Marino       p += strlen ("R ");
3865cf7f2e2dSJohn Marino       trace_regblock_size = strtol (p, &p, 16);
3866cf7f2e2dSJohn Marino     }
3867cf7f2e2dSJohn Marino   else if (strncmp (p, "status ", strlen ("status ")) == 0)
3868cf7f2e2dSJohn Marino     {
3869cf7f2e2dSJohn Marino       p += strlen ("status ");
3870cf7f2e2dSJohn Marino       parse_trace_status (p, current_trace_status ());
3871cf7f2e2dSJohn Marino     }
3872cf7f2e2dSJohn Marino   else if (strncmp (p, "tp ", strlen ("tp ")) == 0)
3873cf7f2e2dSJohn Marino     {
3874cf7f2e2dSJohn Marino       p += strlen ("tp ");
3875cf7f2e2dSJohn Marino       parse_tracepoint_definition (p, utpp);
3876cf7f2e2dSJohn Marino     }
3877cf7f2e2dSJohn Marino   else if (strncmp (p, "tsv ", strlen ("tsv ")) == 0)
3878cf7f2e2dSJohn Marino     {
3879cf7f2e2dSJohn Marino       p += strlen ("tsv ");
3880cf7f2e2dSJohn Marino       parse_tsv_definition (p, utsvp);
3881cf7f2e2dSJohn Marino     }
3882cf7f2e2dSJohn Marino   else
3883c50c785cSJohn Marino     warning (_("Ignoring trace file definition \"%s\""), line);
3884cf7f2e2dSJohn Marino }
3885cf7f2e2dSJohn Marino 
3886cf7f2e2dSJohn Marino /* Parse the part of trace status syntax that is shared between
3887cf7f2e2dSJohn Marino    the remote protocol and the trace file reader.  */
3888cf7f2e2dSJohn Marino 
3889cf7f2e2dSJohn Marino void
parse_trace_status(char * line,struct trace_status * ts)3890cf7f2e2dSJohn Marino parse_trace_status (char *line, struct trace_status *ts)
3891cf7f2e2dSJohn Marino {
3892a45ae5f8SJohn Marino   char *p = line, *p1, *p2, *p3, *p_temp;
3893a45ae5f8SJohn Marino   int end;
3894cf7f2e2dSJohn Marino   ULONGEST val;
3895cf7f2e2dSJohn Marino 
3896cf7f2e2dSJohn Marino   ts->running_known = 1;
3897cf7f2e2dSJohn Marino   ts->running = (*p++ == '1');
3898cf7f2e2dSJohn Marino   ts->stop_reason = trace_stop_reason_unknown;
3899a45ae5f8SJohn Marino   xfree (ts->stop_desc);
3900a45ae5f8SJohn Marino   ts->stop_desc = NULL;
3901cf7f2e2dSJohn Marino   ts->traceframe_count = -1;
3902cf7f2e2dSJohn Marino   ts->traceframes_created = -1;
3903cf7f2e2dSJohn Marino   ts->buffer_free = -1;
3904cf7f2e2dSJohn Marino   ts->buffer_size = -1;
3905cf7f2e2dSJohn Marino   ts->disconnected_tracing = 0;
3906cf7f2e2dSJohn Marino   ts->circular_buffer = 0;
3907a45ae5f8SJohn Marino   xfree (ts->user_name);
3908a45ae5f8SJohn Marino   ts->user_name = NULL;
3909a45ae5f8SJohn Marino   xfree (ts->notes);
3910a45ae5f8SJohn Marino   ts->notes = NULL;
3911a45ae5f8SJohn Marino   ts->start_time = ts->stop_time = 0;
3912cf7f2e2dSJohn Marino 
3913cf7f2e2dSJohn Marino   while (*p++)
3914cf7f2e2dSJohn Marino     {
3915cf7f2e2dSJohn Marino       p1 = strchr (p, ':');
3916cf7f2e2dSJohn Marino       if (p1 == NULL)
3917cf7f2e2dSJohn Marino 	error (_("Malformed trace status, at %s\n\
3918cf7f2e2dSJohn Marino Status line: '%s'\n"), p, line);
3919a45ae5f8SJohn Marino       p3 = strchr (p, ';');
3920a45ae5f8SJohn Marino       if (p3 == NULL)
3921a45ae5f8SJohn Marino 	p3 = p + strlen (p);
3922cf7f2e2dSJohn Marino       if (strncmp (p, stop_reason_names[trace_buffer_full], p1 - p) == 0)
3923cf7f2e2dSJohn Marino 	{
3924cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
3925cf7f2e2dSJohn Marino 	  ts->stop_reason = trace_buffer_full;
3926cf7f2e2dSJohn Marino 	}
3927cf7f2e2dSJohn Marino       else if (strncmp (p, stop_reason_names[trace_never_run], p1 - p) == 0)
3928cf7f2e2dSJohn Marino 	{
3929cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
3930cf7f2e2dSJohn Marino 	  ts->stop_reason = trace_never_run;
3931cf7f2e2dSJohn Marino 	}
3932c50c785cSJohn Marino       else if (strncmp (p, stop_reason_names[tracepoint_passcount],
3933c50c785cSJohn Marino 			p1 - p) == 0)
3934cf7f2e2dSJohn Marino 	{
3935cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
3936cf7f2e2dSJohn Marino 	  ts->stop_reason = tracepoint_passcount;
3937cf7f2e2dSJohn Marino 	  ts->stopping_tracepoint = val;
3938cf7f2e2dSJohn Marino 	}
3939cf7f2e2dSJohn Marino       else if (strncmp (p, stop_reason_names[tstop_command], p1 - p) == 0)
3940cf7f2e2dSJohn Marino 	{
3941a45ae5f8SJohn Marino 	  p2 = strchr (++p1, ':');
3942a45ae5f8SJohn Marino 	  if (!p2 || p2 > p3)
3943a45ae5f8SJohn Marino 	    {
3944a45ae5f8SJohn Marino 	      /*older style*/
3945a45ae5f8SJohn Marino 	      p2 = p1;
3946a45ae5f8SJohn Marino 	    }
3947a45ae5f8SJohn Marino 	  else if (p2 != p1)
3948a45ae5f8SJohn Marino 	    {
3949a45ae5f8SJohn Marino 	      ts->stop_desc = xmalloc (strlen (line));
3950a45ae5f8SJohn Marino 	      end = hex2bin (p1, ts->stop_desc, (p2 - p1) / 2);
3951a45ae5f8SJohn Marino 	      ts->stop_desc[end] = '\0';
3952a45ae5f8SJohn Marino 	    }
3953a45ae5f8SJohn Marino 	  else
3954a45ae5f8SJohn Marino 	    ts->stop_desc = xstrdup ("");
3955a45ae5f8SJohn Marino 
3956a45ae5f8SJohn Marino 	  p = unpack_varlen_hex (++p2, &val);
3957cf7f2e2dSJohn Marino 	  ts->stop_reason = tstop_command;
3958cf7f2e2dSJohn Marino 	}
3959cf7f2e2dSJohn Marino       else if (strncmp (p, stop_reason_names[trace_disconnected], p1 - p) == 0)
3960cf7f2e2dSJohn Marino 	{
3961cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
3962cf7f2e2dSJohn Marino 	  ts->stop_reason = trace_disconnected;
3963cf7f2e2dSJohn Marino 	}
3964cf7f2e2dSJohn Marino       else if (strncmp (p, stop_reason_names[tracepoint_error], p1 - p) == 0)
3965cf7f2e2dSJohn Marino 	{
3966cf7f2e2dSJohn Marino 	  p2 = strchr (++p1, ':');
3967cf7f2e2dSJohn Marino 	  if (p2 != p1)
3968cf7f2e2dSJohn Marino 	    {
3969a45ae5f8SJohn Marino 	      ts->stop_desc = xmalloc ((p2 - p1) / 2 + 1);
3970a45ae5f8SJohn Marino 	      end = hex2bin (p1, ts->stop_desc, (p2 - p1) / 2);
3971a45ae5f8SJohn Marino 	      ts->stop_desc[end] = '\0';
3972cf7f2e2dSJohn Marino 	    }
3973cf7f2e2dSJohn Marino 	  else
3974a45ae5f8SJohn Marino 	    ts->stop_desc = xstrdup ("");
3975cf7f2e2dSJohn Marino 
3976cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p2, &val);
3977cf7f2e2dSJohn Marino 	  ts->stopping_tracepoint = val;
3978cf7f2e2dSJohn Marino 	  ts->stop_reason = tracepoint_error;
3979cf7f2e2dSJohn Marino 	}
3980cf7f2e2dSJohn Marino       else if (strncmp (p, "tframes", p1 - p) == 0)
3981cf7f2e2dSJohn Marino 	{
3982cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
3983cf7f2e2dSJohn Marino 	  ts->traceframe_count = val;
3984cf7f2e2dSJohn Marino 	}
3985cf7f2e2dSJohn Marino       else if (strncmp (p, "tcreated", p1 - p) == 0)
3986cf7f2e2dSJohn Marino 	{
3987cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
3988cf7f2e2dSJohn Marino 	  ts->traceframes_created = val;
3989cf7f2e2dSJohn Marino 	}
3990cf7f2e2dSJohn Marino       else if (strncmp (p, "tfree", p1 - p) == 0)
3991cf7f2e2dSJohn Marino 	{
3992cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
3993cf7f2e2dSJohn Marino 	  ts->buffer_free = val;
3994cf7f2e2dSJohn Marino 	}
3995cf7f2e2dSJohn Marino       else if (strncmp (p, "tsize", p1 - p) == 0)
3996cf7f2e2dSJohn Marino 	{
3997cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
3998cf7f2e2dSJohn Marino 	  ts->buffer_size = val;
3999cf7f2e2dSJohn Marino 	}
4000cf7f2e2dSJohn Marino       else if (strncmp (p, "disconn", p1 - p) == 0)
4001cf7f2e2dSJohn Marino 	{
4002cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
4003cf7f2e2dSJohn Marino 	  ts->disconnected_tracing = val;
4004cf7f2e2dSJohn Marino 	}
4005cf7f2e2dSJohn Marino       else if (strncmp (p, "circular", p1 - p) == 0)
4006cf7f2e2dSJohn Marino 	{
4007cf7f2e2dSJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
4008cf7f2e2dSJohn Marino 	  ts->circular_buffer = val;
4009cf7f2e2dSJohn Marino 	}
4010a45ae5f8SJohn Marino       else if (strncmp (p, "starttime", p1 - p) == 0)
4011a45ae5f8SJohn Marino 	{
4012a45ae5f8SJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
4013a45ae5f8SJohn Marino 	  ts->start_time = val;
4014a45ae5f8SJohn Marino 	}
4015a45ae5f8SJohn Marino       else if (strncmp (p, "stoptime", p1 - p) == 0)
4016a45ae5f8SJohn Marino 	{
4017a45ae5f8SJohn Marino 	  p = unpack_varlen_hex (++p1, &val);
4018a45ae5f8SJohn Marino 	  ts->stop_time = val;
4019a45ae5f8SJohn Marino 	}
4020a45ae5f8SJohn Marino       else if (strncmp (p, "username", p1 - p) == 0)
4021a45ae5f8SJohn Marino 	{
4022a45ae5f8SJohn Marino 	  ++p1;
4023a45ae5f8SJohn Marino 	  ts->user_name = xmalloc (strlen (p) / 2);
4024a45ae5f8SJohn Marino 	  end = hex2bin (p1, ts->user_name, (p3 - p1)  / 2);
4025a45ae5f8SJohn Marino 	  ts->user_name[end] = '\0';
4026a45ae5f8SJohn Marino 	  p = p3;
4027a45ae5f8SJohn Marino 	}
4028a45ae5f8SJohn Marino       else if (strncmp (p, "notes", p1 - p) == 0)
4029a45ae5f8SJohn Marino 	{
4030a45ae5f8SJohn Marino 	  ++p1;
4031a45ae5f8SJohn Marino 	  ts->notes = xmalloc (strlen (p) / 2);
4032a45ae5f8SJohn Marino 	  end = hex2bin (p1, ts->notes, (p3 - p1) / 2);
4033a45ae5f8SJohn Marino 	  ts->notes[end] = '\0';
4034a45ae5f8SJohn Marino 	  p = p3;
4035a45ae5f8SJohn Marino 	}
4036cf7f2e2dSJohn Marino       else
4037cf7f2e2dSJohn Marino 	{
4038cf7f2e2dSJohn Marino 	  /* Silently skip unknown optional info.  */
4039cf7f2e2dSJohn Marino 	  p_temp = strchr (p1 + 1, ';');
4040cf7f2e2dSJohn Marino 	  if (p_temp)
4041cf7f2e2dSJohn Marino 	    p = p_temp;
4042cf7f2e2dSJohn Marino 	  else
4043cf7f2e2dSJohn Marino 	    /* Must be at the end.  */
4044cf7f2e2dSJohn Marino 	    break;
4045cf7f2e2dSJohn Marino 	}
4046cf7f2e2dSJohn Marino     }
4047cf7f2e2dSJohn Marino }
4048cf7f2e2dSJohn Marino 
4049a45ae5f8SJohn Marino void
parse_tracepoint_status(char * p,struct breakpoint * bp,struct uploaded_tp * utp)4050a45ae5f8SJohn Marino parse_tracepoint_status (char *p, struct breakpoint *bp,
4051a45ae5f8SJohn Marino 			 struct uploaded_tp *utp)
4052a45ae5f8SJohn Marino {
4053a45ae5f8SJohn Marino   ULONGEST uval;
4054a45ae5f8SJohn Marino   struct tracepoint *tp = (struct tracepoint *) bp;
4055a45ae5f8SJohn Marino 
4056a45ae5f8SJohn Marino   p = unpack_varlen_hex (p, &uval);
4057a45ae5f8SJohn Marino   if (tp)
4058a45ae5f8SJohn Marino     tp->base.hit_count += uval;
4059a45ae5f8SJohn Marino   else
4060a45ae5f8SJohn Marino     utp->hit_count += uval;
4061a45ae5f8SJohn Marino   p = unpack_varlen_hex (p + 1, &uval);
4062a45ae5f8SJohn Marino   if (tp)
4063a45ae5f8SJohn Marino     tp->traceframe_usage += uval;
4064a45ae5f8SJohn Marino   else
4065a45ae5f8SJohn Marino     utp->traceframe_usage += uval;
4066a45ae5f8SJohn Marino   /* Ignore any extra, allowing for future extensions.  */
4067a45ae5f8SJohn Marino }
4068a45ae5f8SJohn Marino 
4069cf7f2e2dSJohn Marino /* Given a line of text defining a part of a tracepoint, parse it into
4070cf7f2e2dSJohn Marino    an "uploaded tracepoint".  */
4071cf7f2e2dSJohn Marino 
4072cf7f2e2dSJohn Marino void
parse_tracepoint_definition(char * line,struct uploaded_tp ** utpp)4073cf7f2e2dSJohn Marino parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
4074cf7f2e2dSJohn Marino {
4075cf7f2e2dSJohn Marino   char *p;
4076cf7f2e2dSJohn Marino   char piece;
4077cf7f2e2dSJohn Marino   ULONGEST num, addr, step, pass, orig_size, xlen, start;
4078cf7f2e2dSJohn Marino   int enabled, end;
4079cf7f2e2dSJohn Marino   enum bptype type;
4080cf7f2e2dSJohn Marino   char *cond, *srctype, *buf;
4081cf7f2e2dSJohn Marino   struct uploaded_tp *utp = NULL;
4082cf7f2e2dSJohn Marino 
4083cf7f2e2dSJohn Marino   p = line;
4084cf7f2e2dSJohn Marino   /* Both tracepoint and action definitions start with the same number
4085cf7f2e2dSJohn Marino      and address sequence.  */
4086cf7f2e2dSJohn Marino   piece = *p++;
4087cf7f2e2dSJohn Marino   p = unpack_varlen_hex (p, &num);
4088cf7f2e2dSJohn Marino   p++;  /* skip a colon */
4089cf7f2e2dSJohn Marino   p = unpack_varlen_hex (p, &addr);
4090cf7f2e2dSJohn Marino   p++;  /* skip a colon */
4091cf7f2e2dSJohn Marino   if (piece == 'T')
4092cf7f2e2dSJohn Marino     {
4093cf7f2e2dSJohn Marino       enabled = (*p++ == 'E');
4094cf7f2e2dSJohn Marino       p++;  /* skip a colon */
4095cf7f2e2dSJohn Marino       p = unpack_varlen_hex (p, &step);
4096cf7f2e2dSJohn Marino       p++;  /* skip a colon */
4097cf7f2e2dSJohn Marino       p = unpack_varlen_hex (p, &pass);
4098cf7f2e2dSJohn Marino       type = bp_tracepoint;
4099cf7f2e2dSJohn Marino       cond = NULL;
4100cf7f2e2dSJohn Marino       /* Thumb through optional fields.  */
4101cf7f2e2dSJohn Marino       while (*p == ':')
4102cf7f2e2dSJohn Marino 	{
4103cf7f2e2dSJohn Marino 	  p++;  /* skip a colon */
4104cf7f2e2dSJohn Marino 	  if (*p == 'F')
4105cf7f2e2dSJohn Marino 	    {
4106cf7f2e2dSJohn Marino 	      type = bp_fast_tracepoint;
4107cf7f2e2dSJohn Marino 	      p++;
4108cf7f2e2dSJohn Marino 	      p = unpack_varlen_hex (p, &orig_size);
4109cf7f2e2dSJohn Marino 	    }
4110cf7f2e2dSJohn Marino 	  else if (*p == 'S')
4111cf7f2e2dSJohn Marino 	    {
4112cf7f2e2dSJohn Marino 	      type = bp_static_tracepoint;
4113cf7f2e2dSJohn Marino 	      p++;
4114cf7f2e2dSJohn Marino 	    }
4115cf7f2e2dSJohn Marino 	  else if (*p == 'X')
4116cf7f2e2dSJohn Marino 	    {
4117cf7f2e2dSJohn Marino 	      p++;
4118cf7f2e2dSJohn Marino 	      p = unpack_varlen_hex (p, &xlen);
4119cf7f2e2dSJohn Marino 	      p++;  /* skip a comma */
4120cf7f2e2dSJohn Marino 	      cond = (char *) xmalloc (2 * xlen + 1);
4121cf7f2e2dSJohn Marino 	      strncpy (cond, p, 2 * xlen);
4122cf7f2e2dSJohn Marino 	      cond[2 * xlen] = '\0';
4123cf7f2e2dSJohn Marino 	      p += 2 * xlen;
4124cf7f2e2dSJohn Marino 	    }
4125cf7f2e2dSJohn Marino 	  else
4126c50c785cSJohn Marino 	    warning (_("Unrecognized char '%c' in tracepoint "
4127c50c785cSJohn Marino 		       "definition, skipping rest"), *p);
4128cf7f2e2dSJohn Marino 	}
4129cf7f2e2dSJohn Marino       utp = get_uploaded_tp (num, addr, utpp);
4130cf7f2e2dSJohn Marino       utp->type = type;
4131cf7f2e2dSJohn Marino       utp->enabled = enabled;
4132cf7f2e2dSJohn Marino       utp->step = step;
4133cf7f2e2dSJohn Marino       utp->pass = pass;
4134cf7f2e2dSJohn Marino       utp->cond = cond;
4135cf7f2e2dSJohn Marino     }
4136cf7f2e2dSJohn Marino   else if (piece == 'A')
4137cf7f2e2dSJohn Marino     {
4138cf7f2e2dSJohn Marino       utp = get_uploaded_tp (num, addr, utpp);
4139cf7f2e2dSJohn Marino       VEC_safe_push (char_ptr, utp->actions, xstrdup (p));
4140cf7f2e2dSJohn Marino     }
4141cf7f2e2dSJohn Marino   else if (piece == 'S')
4142cf7f2e2dSJohn Marino     {
4143cf7f2e2dSJohn Marino       utp = get_uploaded_tp (num, addr, utpp);
4144cf7f2e2dSJohn Marino       VEC_safe_push (char_ptr, utp->step_actions, xstrdup (p));
4145cf7f2e2dSJohn Marino     }
4146cf7f2e2dSJohn Marino   else if (piece == 'Z')
4147cf7f2e2dSJohn Marino     {
4148cf7f2e2dSJohn Marino       /* Parse a chunk of source form definition.  */
4149cf7f2e2dSJohn Marino       utp = get_uploaded_tp (num, addr, utpp);
4150cf7f2e2dSJohn Marino       srctype = p;
4151cf7f2e2dSJohn Marino       p = strchr (p, ':');
4152cf7f2e2dSJohn Marino       p++;  /* skip a colon */
4153cf7f2e2dSJohn Marino       p = unpack_varlen_hex (p, &start);
4154cf7f2e2dSJohn Marino       p++;  /* skip a colon */
4155cf7f2e2dSJohn Marino       p = unpack_varlen_hex (p, &xlen);
4156cf7f2e2dSJohn Marino       p++;  /* skip a colon */
4157cf7f2e2dSJohn Marino 
4158cf7f2e2dSJohn Marino       buf = alloca (strlen (line));
4159cf7f2e2dSJohn Marino 
4160cf7f2e2dSJohn Marino       end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2);
4161cf7f2e2dSJohn Marino       buf[end] = '\0';
4162cf7f2e2dSJohn Marino 
4163cf7f2e2dSJohn Marino       if (strncmp (srctype, "at:", strlen ("at:")) == 0)
4164cf7f2e2dSJohn Marino 	utp->at_string = xstrdup (buf);
4165cf7f2e2dSJohn Marino       else if (strncmp (srctype, "cond:", strlen ("cond:")) == 0)
4166cf7f2e2dSJohn Marino 	utp->cond_string = xstrdup (buf);
4167cf7f2e2dSJohn Marino       else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0)
4168cf7f2e2dSJohn Marino 	VEC_safe_push (char_ptr, utp->cmd_strings, xstrdup (buf));
4169cf7f2e2dSJohn Marino     }
4170a45ae5f8SJohn Marino   else if (piece == 'V')
4171a45ae5f8SJohn Marino     {
4172a45ae5f8SJohn Marino       utp = get_uploaded_tp (num, addr, utpp);
4173a45ae5f8SJohn Marino 
4174a45ae5f8SJohn Marino       parse_tracepoint_status (p, NULL, utp);
4175a45ae5f8SJohn Marino     }
4176cf7f2e2dSJohn Marino   else
4177cf7f2e2dSJohn Marino     {
4178cf7f2e2dSJohn Marino       /* Don't error out, the target might be sending us optional
4179cf7f2e2dSJohn Marino 	 info that we don't care about.  */
4180cf7f2e2dSJohn Marino       warning (_("Unrecognized tracepoint piece '%c', ignoring"), piece);
4181cf7f2e2dSJohn Marino     }
4182cf7f2e2dSJohn Marino }
4183cf7f2e2dSJohn Marino 
4184cf7f2e2dSJohn Marino /* Convert a textual description of a trace state variable into an
4185cf7f2e2dSJohn Marino    uploaded object.  */
4186cf7f2e2dSJohn Marino 
4187cf7f2e2dSJohn Marino void
parse_tsv_definition(char * line,struct uploaded_tsv ** utsvp)4188cf7f2e2dSJohn Marino parse_tsv_definition (char *line, struct uploaded_tsv **utsvp)
4189cf7f2e2dSJohn Marino {
4190cf7f2e2dSJohn Marino   char *p, *buf;
4191cf7f2e2dSJohn Marino   ULONGEST num, initval, builtin;
4192cf7f2e2dSJohn Marino   int end;
4193cf7f2e2dSJohn Marino   struct uploaded_tsv *utsv = NULL;
4194cf7f2e2dSJohn Marino 
4195cf7f2e2dSJohn Marino   buf = alloca (strlen (line));
4196cf7f2e2dSJohn Marino 
4197cf7f2e2dSJohn Marino   p = line;
4198cf7f2e2dSJohn Marino   p = unpack_varlen_hex (p, &num);
4199cf7f2e2dSJohn Marino   p++; /* skip a colon */
4200cf7f2e2dSJohn Marino   p = unpack_varlen_hex (p, &initval);
4201cf7f2e2dSJohn Marino   p++; /* skip a colon */
4202cf7f2e2dSJohn Marino   p = unpack_varlen_hex (p, &builtin);
4203cf7f2e2dSJohn Marino   p++; /* skip a colon */
4204cf7f2e2dSJohn Marino   end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2);
4205cf7f2e2dSJohn Marino   buf[end] = '\0';
4206cf7f2e2dSJohn Marino 
4207cf7f2e2dSJohn Marino   utsv = get_uploaded_tsv (num, utsvp);
4208cf7f2e2dSJohn Marino   utsv->initial_value = initval;
4209cf7f2e2dSJohn Marino   utsv->builtin = builtin;
4210cf7f2e2dSJohn Marino   utsv->name = xstrdup (buf);
4211cf7f2e2dSJohn Marino }
4212cf7f2e2dSJohn Marino 
4213cf7f2e2dSJohn Marino /* Close the trace file and generally clean up.  */
4214cf7f2e2dSJohn Marino 
4215cf7f2e2dSJohn Marino static void
tfile_close(int quitting)4216cf7f2e2dSJohn Marino tfile_close (int quitting)
4217cf7f2e2dSJohn Marino {
4218cf7f2e2dSJohn Marino   int pid;
4219cf7f2e2dSJohn Marino 
4220cf7f2e2dSJohn Marino   if (trace_fd < 0)
4221cf7f2e2dSJohn Marino     return;
4222cf7f2e2dSJohn Marino 
4223cf7f2e2dSJohn Marino   pid = ptid_get_pid (inferior_ptid);
4224c50c785cSJohn Marino   inferior_ptid = null_ptid;	/* Avoid confusion from thread stuff.  */
4225cf7f2e2dSJohn Marino   exit_inferior_silent (pid);
4226cf7f2e2dSJohn Marino 
4227cf7f2e2dSJohn Marino   close (trace_fd);
4228cf7f2e2dSJohn Marino   trace_fd = -1;
4229cf7f2e2dSJohn Marino   xfree (trace_filename);
4230c50c785cSJohn Marino   trace_filename = NULL;
4231cf7f2e2dSJohn Marino }
4232cf7f2e2dSJohn Marino 
4233cf7f2e2dSJohn Marino static void
tfile_files_info(struct target_ops * t)4234cf7f2e2dSJohn Marino tfile_files_info (struct target_ops *t)
4235cf7f2e2dSJohn Marino {
4236*ef5ccd6cSJohn Marino   printf_filtered ("\t`%s'\n", trace_filename);
4237cf7f2e2dSJohn Marino }
4238cf7f2e2dSJohn Marino 
4239cf7f2e2dSJohn Marino /* The trace status for a file is that tracing can never be run.  */
4240cf7f2e2dSJohn Marino 
4241cf7f2e2dSJohn Marino static int
tfile_get_trace_status(struct trace_status * ts)4242cf7f2e2dSJohn Marino tfile_get_trace_status (struct trace_status *ts)
4243cf7f2e2dSJohn Marino {
4244cf7f2e2dSJohn Marino   /* Other bits of trace status were collected as part of opening the
4245cf7f2e2dSJohn Marino      trace files, so nothing to do here.  */
4246cf7f2e2dSJohn Marino 
4247cf7f2e2dSJohn Marino   return -1;
4248cf7f2e2dSJohn Marino }
4249cf7f2e2dSJohn Marino 
4250a45ae5f8SJohn Marino static void
tfile_get_tracepoint_status(struct breakpoint * tp,struct uploaded_tp * utp)4251a45ae5f8SJohn Marino tfile_get_tracepoint_status (struct breakpoint *tp, struct uploaded_tp *utp)
4252a45ae5f8SJohn Marino {
4253a45ae5f8SJohn Marino   /* Other bits of trace status were collected as part of opening the
4254a45ae5f8SJohn Marino      trace files, so nothing to do here.  */
4255a45ae5f8SJohn Marino }
4256a45ae5f8SJohn Marino 
4257cf7f2e2dSJohn Marino /* Given the position of a traceframe in the file, figure out what
4258cf7f2e2dSJohn Marino    address the frame was collected at.  This would normally be the
4259cf7f2e2dSJohn Marino    value of a collected PC register, but if not available, we
4260cf7f2e2dSJohn Marino    improvise.  */
4261cf7f2e2dSJohn Marino 
4262cf7f2e2dSJohn Marino static ULONGEST
tfile_get_traceframe_address(off_t tframe_offset)4263cf7f2e2dSJohn Marino tfile_get_traceframe_address (off_t tframe_offset)
4264cf7f2e2dSJohn Marino {
4265cf7f2e2dSJohn Marino   ULONGEST addr = 0;
4266cf7f2e2dSJohn Marino   short tpnum;
4267a45ae5f8SJohn Marino   struct tracepoint *tp;
4268cf7f2e2dSJohn Marino   off_t saved_offset = cur_offset;
4269cf7f2e2dSJohn Marino 
4270c50c785cSJohn Marino   /* FIXME dig pc out of collected registers.  */
4271cf7f2e2dSJohn Marino 
4272cf7f2e2dSJohn Marino   /* Fall back to using tracepoint address.  */
4273cf7f2e2dSJohn Marino   lseek (trace_fd, tframe_offset, SEEK_SET);
4274c50c785cSJohn Marino   tfile_read ((gdb_byte *) &tpnum, 2);
4275c50c785cSJohn Marino   tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
4276c50c785cSJohn Marino 					  gdbarch_byte_order
4277*ef5ccd6cSJohn Marino 					      (target_gdbarch ()));
4278cf7f2e2dSJohn Marino 
4279cf7f2e2dSJohn Marino   tp = get_tracepoint_by_number_on_target (tpnum);
4280c50c785cSJohn Marino   /* FIXME this is a poor heuristic if multiple locations.  */
4281a45ae5f8SJohn Marino   if (tp && tp->base.loc)
4282a45ae5f8SJohn Marino     addr = tp->base.loc->address;
4283cf7f2e2dSJohn Marino 
4284cf7f2e2dSJohn Marino   /* Restore our seek position.  */
4285cf7f2e2dSJohn Marino   cur_offset = saved_offset;
4286cf7f2e2dSJohn Marino   lseek (trace_fd, cur_offset, SEEK_SET);
4287cf7f2e2dSJohn Marino   return addr;
4288cf7f2e2dSJohn Marino }
4289cf7f2e2dSJohn Marino 
4290cf7f2e2dSJohn Marino /* Given a type of search and some parameters, scan the collection of
4291cf7f2e2dSJohn Marino    traceframes in the file looking for a match.  When found, return
4292cf7f2e2dSJohn Marino    both the traceframe and tracepoint number, otherwise -1 for
4293cf7f2e2dSJohn Marino    each.  */
4294cf7f2e2dSJohn Marino 
4295cf7f2e2dSJohn Marino static int
tfile_trace_find(enum trace_find_type type,int num,ULONGEST addr1,ULONGEST addr2,int * tpp)4296cf7f2e2dSJohn Marino tfile_trace_find (enum trace_find_type type, int num,
4297cf7f2e2dSJohn Marino 		  ULONGEST addr1, ULONGEST addr2, int *tpp)
4298cf7f2e2dSJohn Marino {
4299cf7f2e2dSJohn Marino   short tpnum;
4300c50c785cSJohn Marino   int tfnum = 0, found = 0;
4301c50c785cSJohn Marino   unsigned int data_size;
4302a45ae5f8SJohn Marino   struct tracepoint *tp;
4303cf7f2e2dSJohn Marino   off_t offset, tframe_offset;
4304cf7f2e2dSJohn Marino   ULONGEST tfaddr;
4305cf7f2e2dSJohn Marino 
4306*ef5ccd6cSJohn Marino   if (num == -1)
4307c50c785cSJohn Marino     {
4308c50c785cSJohn Marino       if (tpp)
4309c50c785cSJohn Marino         *tpp = -1;
4310c50c785cSJohn Marino       return -1;
4311c50c785cSJohn Marino     }
4312c50c785cSJohn Marino 
4313cf7f2e2dSJohn Marino   lseek (trace_fd, trace_frames_offset, SEEK_SET);
4314cf7f2e2dSJohn Marino   offset = trace_frames_offset;
4315cf7f2e2dSJohn Marino   while (1)
4316cf7f2e2dSJohn Marino     {
4317cf7f2e2dSJohn Marino       tframe_offset = offset;
4318c50c785cSJohn Marino       tfile_read ((gdb_byte *) &tpnum, 2);
4319c50c785cSJohn Marino       tpnum = (short) extract_signed_integer ((gdb_byte *) &tpnum, 2,
4320c50c785cSJohn Marino 					      gdbarch_byte_order
4321*ef5ccd6cSJohn Marino 						  (target_gdbarch ()));
4322cf7f2e2dSJohn Marino       offset += 2;
4323cf7f2e2dSJohn Marino       if (tpnum == 0)
4324cf7f2e2dSJohn Marino 	break;
4325c50c785cSJohn Marino       tfile_read ((gdb_byte *) &data_size, 4);
4326c50c785cSJohn Marino       data_size = (unsigned int) extract_unsigned_integer
4327c50c785cSJohn Marino                                      ((gdb_byte *) &data_size, 4,
4328*ef5ccd6cSJohn Marino 				      gdbarch_byte_order (target_gdbarch ()));
4329cf7f2e2dSJohn Marino       offset += 4;
4330*ef5ccd6cSJohn Marino 
4331*ef5ccd6cSJohn Marino       if (type == tfind_number)
4332cf7f2e2dSJohn Marino 	{
4333*ef5ccd6cSJohn Marino 	  /* Looking for a specific trace frame.  */
4334cf7f2e2dSJohn Marino 	  if (tfnum == num)
4335cf7f2e2dSJohn Marino 	    found = 1;
4336*ef5ccd6cSJohn Marino 	}
4337*ef5ccd6cSJohn Marino       else
4338*ef5ccd6cSJohn Marino 	{
4339*ef5ccd6cSJohn Marino 	  /* Start from the _next_ trace frame.  */
4340*ef5ccd6cSJohn Marino 	  if (tfnum > traceframe_number)
4341*ef5ccd6cSJohn Marino 	    {
4342*ef5ccd6cSJohn Marino 	      switch (type)
4343*ef5ccd6cSJohn Marino 		{
4344cf7f2e2dSJohn Marino 		case tfind_pc:
4345cf7f2e2dSJohn Marino 		  tfaddr = tfile_get_traceframe_address (tframe_offset);
4346cf7f2e2dSJohn Marino 		  if (tfaddr == addr1)
4347cf7f2e2dSJohn Marino 		    found = 1;
4348cf7f2e2dSJohn Marino 		  break;
4349cf7f2e2dSJohn Marino 		case tfind_tp:
4350cf7f2e2dSJohn Marino 		  tp = get_tracepoint (num);
4351cf7f2e2dSJohn Marino 		  if (tp && tpnum == tp->number_on_target)
4352cf7f2e2dSJohn Marino 		    found = 1;
4353cf7f2e2dSJohn Marino 		  break;
4354cf7f2e2dSJohn Marino 		case tfind_range:
4355cf7f2e2dSJohn Marino 		  tfaddr = tfile_get_traceframe_address (tframe_offset);
4356cf7f2e2dSJohn Marino 		  if (addr1 <= tfaddr && tfaddr <= addr2)
4357cf7f2e2dSJohn Marino 		    found = 1;
4358cf7f2e2dSJohn Marino 		  break;
4359cf7f2e2dSJohn Marino 		case tfind_outside:
4360cf7f2e2dSJohn Marino 		  tfaddr = tfile_get_traceframe_address (tframe_offset);
4361cf7f2e2dSJohn Marino 		  if (!(addr1 <= tfaddr && tfaddr <= addr2))
4362cf7f2e2dSJohn Marino 		    found = 1;
4363cf7f2e2dSJohn Marino 		  break;
4364cf7f2e2dSJohn Marino 		default:
4365cf7f2e2dSJohn Marino 		  internal_error (__FILE__, __LINE__, _("unknown tfind type"));
4366cf7f2e2dSJohn Marino 		}
4367*ef5ccd6cSJohn Marino 	    }
4368*ef5ccd6cSJohn Marino 	}
4369*ef5ccd6cSJohn Marino 
4370cf7f2e2dSJohn Marino       if (found)
4371cf7f2e2dSJohn Marino 	{
4372cf7f2e2dSJohn Marino 	  if (tpp)
4373cf7f2e2dSJohn Marino 	    *tpp = tpnum;
4374cf7f2e2dSJohn Marino 	  cur_offset = offset;
4375cf7f2e2dSJohn Marino 	  cur_data_size = data_size;
4376*ef5ccd6cSJohn Marino 
4377cf7f2e2dSJohn Marino 	  return tfnum;
4378cf7f2e2dSJohn Marino 	}
4379cf7f2e2dSJohn Marino       /* Skip past the traceframe's data.  */
4380cf7f2e2dSJohn Marino       lseek (trace_fd, data_size, SEEK_CUR);
4381cf7f2e2dSJohn Marino       offset += data_size;
4382cf7f2e2dSJohn Marino       /* Update our own count of traceframes.  */
4383cf7f2e2dSJohn Marino       ++tfnum;
4384cf7f2e2dSJohn Marino     }
4385cf7f2e2dSJohn Marino   /* Did not find what we were looking for.  */
4386cf7f2e2dSJohn Marino   if (tpp)
4387cf7f2e2dSJohn Marino     *tpp = -1;
4388cf7f2e2dSJohn Marino   return -1;
4389cf7f2e2dSJohn Marino }
4390cf7f2e2dSJohn Marino 
4391c50c785cSJohn Marino /* Prototype of the callback passed to tframe_walk_blocks.  */
4392c50c785cSJohn Marino typedef int (*walk_blocks_callback_func) (char blocktype, void *data);
4393c50c785cSJohn Marino 
4394c50c785cSJohn Marino /* Callback for traceframe_walk_blocks, used to find a given block
4395c50c785cSJohn Marino    type in a traceframe.  */
4396c50c785cSJohn Marino 
4397c50c785cSJohn Marino static int
match_blocktype(char blocktype,void * data)4398c50c785cSJohn Marino match_blocktype (char blocktype, void *data)
4399c50c785cSJohn Marino {
4400c50c785cSJohn Marino   char *wantedp = data;
4401c50c785cSJohn Marino 
4402c50c785cSJohn Marino   if (*wantedp == blocktype)
4403c50c785cSJohn Marino     return 1;
4404c50c785cSJohn Marino 
4405c50c785cSJohn Marino   return 0;
4406c50c785cSJohn Marino }
4407c50c785cSJohn Marino 
4408c50c785cSJohn Marino /* Walk over all traceframe block starting at POS offset from
4409c50c785cSJohn Marino    CUR_OFFSET, and call CALLBACK for each block found, passing in DATA
4410c50c785cSJohn Marino    unmodified.  If CALLBACK returns true, this returns the position in
4411c50c785cSJohn Marino    the traceframe where the block is found, relative to the start of
4412c50c785cSJohn Marino    the traceframe (cur_offset).  Returns -1 if no callback call
4413c50c785cSJohn Marino    returned true, indicating that all blocks have been walked.  */
4414c50c785cSJohn Marino 
4415c50c785cSJohn Marino static int
traceframe_walk_blocks(walk_blocks_callback_func callback,int pos,void * data)4416c50c785cSJohn Marino traceframe_walk_blocks (walk_blocks_callback_func callback,
4417c50c785cSJohn Marino 			int pos, void *data)
4418c50c785cSJohn Marino {
4419c50c785cSJohn Marino   /* Iterate through a traceframe's blocks, looking for a block of the
4420c50c785cSJohn Marino      requested type.  */
4421c50c785cSJohn Marino 
4422c50c785cSJohn Marino   lseek (trace_fd, cur_offset + pos, SEEK_SET);
4423c50c785cSJohn Marino   while (pos < cur_data_size)
4424c50c785cSJohn Marino     {
4425c50c785cSJohn Marino       unsigned short mlen;
4426c50c785cSJohn Marino       char block_type;
4427c50c785cSJohn Marino 
4428c50c785cSJohn Marino       tfile_read (&block_type, 1);
4429c50c785cSJohn Marino 
4430c50c785cSJohn Marino       ++pos;
4431c50c785cSJohn Marino 
4432c50c785cSJohn Marino       if ((*callback) (block_type, data))
4433c50c785cSJohn Marino 	return pos;
4434c50c785cSJohn Marino 
4435c50c785cSJohn Marino       switch (block_type)
4436c50c785cSJohn Marino 	{
4437c50c785cSJohn Marino 	case 'R':
4438c50c785cSJohn Marino 	  lseek (trace_fd, cur_offset + pos + trace_regblock_size, SEEK_SET);
4439c50c785cSJohn Marino 	  pos += trace_regblock_size;
4440c50c785cSJohn Marino 	  break;
4441c50c785cSJohn Marino 	case 'M':
4442c50c785cSJohn Marino 	  lseek (trace_fd, cur_offset + pos + 8, SEEK_SET);
4443c50c785cSJohn Marino 	  tfile_read ((gdb_byte *) &mlen, 2);
4444c50c785cSJohn Marino           mlen = (unsigned short)
4445c50c785cSJohn Marino                 extract_unsigned_integer ((gdb_byte *) &mlen, 2,
4446c50c785cSJohn Marino                                           gdbarch_byte_order
4447*ef5ccd6cSJohn Marino                                               (target_gdbarch ()));
4448c50c785cSJohn Marino 	  lseek (trace_fd, mlen, SEEK_CUR);
4449c50c785cSJohn Marino 	  pos += (8 + 2 + mlen);
4450c50c785cSJohn Marino 	  break;
4451c50c785cSJohn Marino 	case 'V':
4452c50c785cSJohn Marino 	  lseek (trace_fd, cur_offset + pos + 4 + 8, SEEK_SET);
4453c50c785cSJohn Marino 	  pos += (4 + 8);
4454c50c785cSJohn Marino 	  break;
4455c50c785cSJohn Marino 	default:
4456c50c785cSJohn Marino 	  error (_("Unknown block type '%c' (0x%x) in trace frame"),
4457c50c785cSJohn Marino 		 block_type, block_type);
4458c50c785cSJohn Marino 	  break;
4459c50c785cSJohn Marino 	}
4460c50c785cSJohn Marino     }
4461c50c785cSJohn Marino 
4462c50c785cSJohn Marino   return -1;
4463c50c785cSJohn Marino }
4464c50c785cSJohn Marino 
4465c50c785cSJohn Marino /* Convenience wrapper around traceframe_walk_blocks.  Looks for the
4466c50c785cSJohn Marino    position offset of a block of type TYPE_WANTED in the current trace
4467c50c785cSJohn Marino    frame, starting at POS.  Returns -1 if no such block was found.  */
4468c50c785cSJohn Marino 
4469c50c785cSJohn Marino static int
traceframe_find_block_type(char type_wanted,int pos)4470c50c785cSJohn Marino traceframe_find_block_type (char type_wanted, int pos)
4471c50c785cSJohn Marino {
4472c50c785cSJohn Marino   return traceframe_walk_blocks (match_blocktype, pos, &type_wanted);
4473c50c785cSJohn Marino }
4474c50c785cSJohn Marino 
4475cf7f2e2dSJohn Marino /* Look for a block of saved registers in the traceframe, and get the
4476cf7f2e2dSJohn Marino    requested register from it.  */
4477cf7f2e2dSJohn Marino 
4478cf7f2e2dSJohn Marino static void
tfile_fetch_registers(struct target_ops * ops,struct regcache * regcache,int regno)4479cf7f2e2dSJohn Marino tfile_fetch_registers (struct target_ops *ops,
4480cf7f2e2dSJohn Marino 		       struct regcache *regcache, int regno)
4481cf7f2e2dSJohn Marino {
4482cf7f2e2dSJohn Marino   struct gdbarch *gdbarch = get_regcache_arch (regcache);
4483*ef5ccd6cSJohn Marino   int offset, regn, regsize, pc_regno;
4484cf7f2e2dSJohn Marino   char *regs;
4485cf7f2e2dSJohn Marino 
4486cf7f2e2dSJohn Marino   /* An uninitialized reg size says we're not going to be
4487cf7f2e2dSJohn Marino      successful at getting register blocks.  */
4488cf7f2e2dSJohn Marino   if (!trace_regblock_size)
4489cf7f2e2dSJohn Marino     return;
4490cf7f2e2dSJohn Marino 
4491cf7f2e2dSJohn Marino   regs = alloca (trace_regblock_size);
4492cf7f2e2dSJohn Marino 
4493c50c785cSJohn Marino   if (traceframe_find_block_type ('R', 0) >= 0)
4494cf7f2e2dSJohn Marino     {
4495c50c785cSJohn Marino       tfile_read (regs, trace_regblock_size);
4496cf7f2e2dSJohn Marino 
4497cf7f2e2dSJohn Marino       /* Assume the block is laid out in GDB register number order,
4498cf7f2e2dSJohn Marino 	 each register with the size that it has in GDB.  */
4499cf7f2e2dSJohn Marino       offset = 0;
4500cf7f2e2dSJohn Marino       for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
4501cf7f2e2dSJohn Marino 	{
4502cf7f2e2dSJohn Marino 	  regsize = register_size (gdbarch, regn);
4503cf7f2e2dSJohn Marino 	  /* Make sure we stay within block bounds.  */
4504cf7f2e2dSJohn Marino 	  if (offset + regsize >= trace_regblock_size)
4505cf7f2e2dSJohn Marino 	    break;
4506c50c785cSJohn Marino 	  if (regcache_register_status (regcache, regn) == REG_UNKNOWN)
4507cf7f2e2dSJohn Marino 	    {
4508cf7f2e2dSJohn Marino 	      if (regno == regn)
4509cf7f2e2dSJohn Marino 		{
4510cf7f2e2dSJohn Marino 		  regcache_raw_supply (regcache, regno, regs + offset);
4511cf7f2e2dSJohn Marino 		  break;
4512cf7f2e2dSJohn Marino 		}
4513cf7f2e2dSJohn Marino 	      else if (regno == -1)
4514cf7f2e2dSJohn Marino 		{
4515cf7f2e2dSJohn Marino 		  regcache_raw_supply (regcache, regn, regs + offset);
4516cf7f2e2dSJohn Marino 		}
4517cf7f2e2dSJohn Marino 	    }
4518cf7f2e2dSJohn Marino 	  offset += regsize;
4519cf7f2e2dSJohn Marino 	}
4520cf7f2e2dSJohn Marino       return;
4521cf7f2e2dSJohn Marino     }
4522cf7f2e2dSJohn Marino 
4523c50c785cSJohn Marino   /* We get here if no register data has been found.  Mark registers
4524c50c785cSJohn Marino      as unavailable.  */
4525cf7f2e2dSJohn Marino   for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++)
4526cf7f2e2dSJohn Marino     regcache_raw_supply (regcache, regn, NULL);
4527cf7f2e2dSJohn Marino 
4528cf7f2e2dSJohn Marino   /* We can often usefully guess that the PC is going to be the same
4529cf7f2e2dSJohn Marino      as the address of the tracepoint.  */
4530cf7f2e2dSJohn Marino   pc_regno = gdbarch_pc_regnum (gdbarch);
4531cf7f2e2dSJohn Marino   if (pc_regno >= 0 && (regno == -1 || regno == pc_regno))
4532cf7f2e2dSJohn Marino     {
4533a45ae5f8SJohn Marino       struct tracepoint *tp = get_tracepoint (tracepoint_number);
4534cf7f2e2dSJohn Marino 
4535a45ae5f8SJohn Marino       if (tp && tp->base.loc)
4536cf7f2e2dSJohn Marino 	{
4537cf7f2e2dSJohn Marino 	  /* But don't try to guess if tracepoint is multi-location...  */
4538a45ae5f8SJohn Marino 	  if (tp->base.loc->next)
4539cf7f2e2dSJohn Marino 	    {
4540c50c785cSJohn Marino 	      warning (_("Tracepoint %d has multiple "
4541c50c785cSJohn Marino 			 "locations, cannot infer $pc"),
4542a45ae5f8SJohn Marino 		       tp->base.number);
4543cf7f2e2dSJohn Marino 	      return;
4544cf7f2e2dSJohn Marino 	    }
4545cf7f2e2dSJohn Marino 	  /* ... or does while-stepping.  */
4546cf7f2e2dSJohn Marino 	  if (tp->step_count > 0)
4547cf7f2e2dSJohn Marino 	    {
4548c50c785cSJohn Marino 	      warning (_("Tracepoint %d does while-stepping, "
4549c50c785cSJohn Marino 			 "cannot infer $pc"),
4550a45ae5f8SJohn Marino 		       tp->base.number);
4551cf7f2e2dSJohn Marino 	      return;
4552cf7f2e2dSJohn Marino 	    }
4553cf7f2e2dSJohn Marino 
4554cf7f2e2dSJohn Marino 	  store_unsigned_integer (regs, register_size (gdbarch, pc_regno),
4555cf7f2e2dSJohn Marino 				  gdbarch_byte_order (gdbarch),
4556a45ae5f8SJohn Marino 				  tp->base.loc->address);
4557cf7f2e2dSJohn Marino 	  regcache_raw_supply (regcache, pc_regno, regs);
4558cf7f2e2dSJohn Marino 	}
4559cf7f2e2dSJohn Marino     }
4560cf7f2e2dSJohn Marino }
4561cf7f2e2dSJohn Marino 
4562cf7f2e2dSJohn Marino static LONGEST
tfile_xfer_partial(struct target_ops * ops,enum target_object object,const char * annex,gdb_byte * readbuf,const gdb_byte * writebuf,ULONGEST offset,LONGEST len)4563cf7f2e2dSJohn Marino tfile_xfer_partial (struct target_ops *ops, enum target_object object,
4564cf7f2e2dSJohn Marino 		    const char *annex, gdb_byte *readbuf,
4565cf7f2e2dSJohn Marino 		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
4566cf7f2e2dSJohn Marino {
4567cf7f2e2dSJohn Marino   /* We're only doing regular memory for now.  */
4568cf7f2e2dSJohn Marino   if (object != TARGET_OBJECT_MEMORY)
4569cf7f2e2dSJohn Marino     return -1;
4570cf7f2e2dSJohn Marino 
4571cf7f2e2dSJohn Marino   if (readbuf == NULL)
4572c50c785cSJohn Marino     error (_("tfile_xfer_partial: trace file is read-only"));
4573cf7f2e2dSJohn Marino 
4574c50c785cSJohn Marino  if (traceframe_number != -1)
4575c50c785cSJohn Marino     {
4576c50c785cSJohn Marino       int pos = 0;
4577c50c785cSJohn Marino 
4578c50c785cSJohn Marino       /* Iterate through the traceframe's blocks, looking for
4579c50c785cSJohn Marino 	 memory.  */
4580c50c785cSJohn Marino       while ((pos = traceframe_find_block_type ('M', pos)) >= 0)
4581c50c785cSJohn Marino 	{
4582c50c785cSJohn Marino 	  ULONGEST maddr, amt;
4583c50c785cSJohn Marino 	  unsigned short mlen;
4584*ef5ccd6cSJohn Marino 	  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
4585c50c785cSJohn Marino 
4586c50c785cSJohn Marino 	  tfile_read ((gdb_byte *) &maddr, 8);
4587c50c785cSJohn Marino 	  maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8,
4588c50c785cSJohn Marino 					    byte_order);
4589c50c785cSJohn Marino 	  tfile_read ((gdb_byte *) &mlen, 2);
4590c50c785cSJohn Marino 	  mlen = (unsigned short)
4591c50c785cSJohn Marino 	    extract_unsigned_integer ((gdb_byte *) &mlen, 2, byte_order);
4592c50c785cSJohn Marino 
4593cf7f2e2dSJohn Marino 	  /* If the block includes the first part of the desired
4594cf7f2e2dSJohn Marino 	     range, return as much it has; GDB will re-request the
4595cf7f2e2dSJohn Marino 	     remainder, which might be in a different block of this
4596cf7f2e2dSJohn Marino 	     trace frame.  */
4597cf7f2e2dSJohn Marino 	  if (maddr <= offset && offset < (maddr + mlen))
4598cf7f2e2dSJohn Marino 	    {
4599cf7f2e2dSJohn Marino 	      amt = (maddr + mlen) - offset;
4600cf7f2e2dSJohn Marino 	      if (amt > len)
4601cf7f2e2dSJohn Marino 		amt = len;
4602cf7f2e2dSJohn Marino 
4603*ef5ccd6cSJohn Marino 	      if (maddr != offset)
4604*ef5ccd6cSJohn Marino 	        lseek (trace_fd, offset - maddr, SEEK_CUR);
4605c50c785cSJohn Marino 	      tfile_read (readbuf, amt);
4606cf7f2e2dSJohn Marino 	      return amt;
4607cf7f2e2dSJohn Marino 	    }
4608c50c785cSJohn Marino 
4609c50c785cSJohn Marino 	  /* Skip over this block.  */
4610cf7f2e2dSJohn Marino 	  pos += (8 + 2 + mlen);
4611cf7f2e2dSJohn Marino 	}
4612cf7f2e2dSJohn Marino     }
4613cf7f2e2dSJohn Marino 
4614cf7f2e2dSJohn Marino   /* It's unduly pedantic to refuse to look at the executable for
4615cf7f2e2dSJohn Marino      read-only pieces; so do the equivalent of readonly regions aka
4616cf7f2e2dSJohn Marino      QTro packet.  */
4617c50c785cSJohn Marino   /* FIXME account for relocation at some point.  */
4618cf7f2e2dSJohn Marino   if (exec_bfd)
4619cf7f2e2dSJohn Marino     {
4620cf7f2e2dSJohn Marino       asection *s;
4621cf7f2e2dSJohn Marino       bfd_size_type size;
4622c50c785cSJohn Marino       bfd_vma vma;
4623cf7f2e2dSJohn Marino 
4624cf7f2e2dSJohn Marino       for (s = exec_bfd->sections; s; s = s->next)
4625cf7f2e2dSJohn Marino 	{
4626c50c785cSJohn Marino 	  if ((s->flags & SEC_LOAD) == 0
4627c50c785cSJohn Marino 	      || (s->flags & SEC_READONLY) == 0)
4628cf7f2e2dSJohn Marino 	    continue;
4629cf7f2e2dSJohn Marino 
4630c50c785cSJohn Marino 	  vma = s->vma;
4631cf7f2e2dSJohn Marino 	  size = bfd_get_section_size (s);
4632c50c785cSJohn Marino 	  if (vma <= offset && offset < (vma + size))
4633cf7f2e2dSJohn Marino 	    {
4634c50c785cSJohn Marino 	      ULONGEST amt;
4635c50c785cSJohn Marino 
4636c50c785cSJohn Marino 	      amt = (vma + size) - offset;
4637cf7f2e2dSJohn Marino 	      if (amt > len)
4638cf7f2e2dSJohn Marino 		amt = len;
4639cf7f2e2dSJohn Marino 
4640cf7f2e2dSJohn Marino 	      amt = bfd_get_section_contents (exec_bfd, s,
4641c50c785cSJohn Marino 					      readbuf, offset - vma, amt);
4642cf7f2e2dSJohn Marino 	      return amt;
4643cf7f2e2dSJohn Marino 	    }
4644cf7f2e2dSJohn Marino 	}
4645cf7f2e2dSJohn Marino     }
4646cf7f2e2dSJohn Marino 
4647cf7f2e2dSJohn Marino   /* Indicate failure to find the requested memory block.  */
4648cf7f2e2dSJohn Marino   return -1;
4649cf7f2e2dSJohn Marino }
4650cf7f2e2dSJohn Marino 
4651cf7f2e2dSJohn Marino /* Iterate through the blocks of a trace frame, looking for a 'V'
4652cf7f2e2dSJohn Marino    block with a matching tsv number.  */
4653cf7f2e2dSJohn Marino 
4654cf7f2e2dSJohn Marino static int
tfile_get_trace_state_variable_value(int tsvnum,LONGEST * val)4655cf7f2e2dSJohn Marino tfile_get_trace_state_variable_value (int tsvnum, LONGEST *val)
4656cf7f2e2dSJohn Marino {
4657c50c785cSJohn Marino   int pos;
4658cf7f2e2dSJohn Marino 
4659cf7f2e2dSJohn Marino   pos = 0;
4660c50c785cSJohn Marino   while ((pos = traceframe_find_block_type ('V', pos)) >= 0)
4661cf7f2e2dSJohn Marino     {
4662c50c785cSJohn Marino       int vnum;
4663c50c785cSJohn Marino 
4664c50c785cSJohn Marino       tfile_read ((gdb_byte *) &vnum, 4);
4665c50c785cSJohn Marino       vnum = (int) extract_signed_integer ((gdb_byte *) &vnum, 4,
4666c50c785cSJohn Marino 					   gdbarch_byte_order
4667*ef5ccd6cSJohn Marino 					   (target_gdbarch ()));
4668cf7f2e2dSJohn Marino       if (tsvnum == vnum)
4669cf7f2e2dSJohn Marino 	{
4670c50c785cSJohn Marino 	  tfile_read ((gdb_byte *) val, 8);
4671c50c785cSJohn Marino 	  *val = extract_signed_integer ((gdb_byte *) val, 8,
4672c50c785cSJohn Marino 					 gdbarch_byte_order
4673*ef5ccd6cSJohn Marino 					 (target_gdbarch ()));
4674cf7f2e2dSJohn Marino 	  return 1;
4675cf7f2e2dSJohn Marino 	}
4676cf7f2e2dSJohn Marino       pos += (4 + 8);
4677cf7f2e2dSJohn Marino     }
4678c50c785cSJohn Marino 
4679cf7f2e2dSJohn Marino   /* Didn't find anything.  */
4680cf7f2e2dSJohn Marino   return 0;
4681cf7f2e2dSJohn Marino }
4682cf7f2e2dSJohn Marino 
4683cf7f2e2dSJohn Marino static int
tfile_has_all_memory(struct target_ops * ops)4684cf7f2e2dSJohn Marino tfile_has_all_memory (struct target_ops *ops)
4685cf7f2e2dSJohn Marino {
4686cf7f2e2dSJohn Marino   return 1;
4687cf7f2e2dSJohn Marino }
4688cf7f2e2dSJohn Marino 
4689cf7f2e2dSJohn Marino static int
tfile_has_memory(struct target_ops * ops)4690cf7f2e2dSJohn Marino tfile_has_memory (struct target_ops *ops)
4691cf7f2e2dSJohn Marino {
4692cf7f2e2dSJohn Marino   return 1;
4693cf7f2e2dSJohn Marino }
4694cf7f2e2dSJohn Marino 
4695cf7f2e2dSJohn Marino static int
tfile_has_stack(struct target_ops * ops)4696cf7f2e2dSJohn Marino tfile_has_stack (struct target_ops *ops)
4697cf7f2e2dSJohn Marino {
4698c50c785cSJohn Marino   return traceframe_number != -1;
4699cf7f2e2dSJohn Marino }
4700cf7f2e2dSJohn Marino 
4701cf7f2e2dSJohn Marino static int
tfile_has_registers(struct target_ops * ops)4702cf7f2e2dSJohn Marino tfile_has_registers (struct target_ops *ops)
4703cf7f2e2dSJohn Marino {
4704c50c785cSJohn Marino   return traceframe_number != -1;
4705c50c785cSJohn Marino }
4706c50c785cSJohn Marino 
4707c50c785cSJohn Marino static int
tfile_thread_alive(struct target_ops * ops,ptid_t ptid)4708c50c785cSJohn Marino tfile_thread_alive (struct target_ops *ops, ptid_t ptid)
4709c50c785cSJohn Marino {
4710cf7f2e2dSJohn Marino   return 1;
4711cf7f2e2dSJohn Marino }
4712cf7f2e2dSJohn Marino 
4713c50c785cSJohn Marino /* Callback for traceframe_walk_blocks.  Builds a traceframe_info
4714c50c785cSJohn Marino    object for the tfile target's current traceframe.  */
4715c50c785cSJohn Marino 
4716c50c785cSJohn Marino static int
build_traceframe_info(char blocktype,void * data)4717c50c785cSJohn Marino build_traceframe_info (char blocktype, void *data)
4718c50c785cSJohn Marino {
4719c50c785cSJohn Marino   struct traceframe_info *info = data;
4720c50c785cSJohn Marino 
4721c50c785cSJohn Marino   switch (blocktype)
4722c50c785cSJohn Marino     {
4723c50c785cSJohn Marino     case 'M':
4724c50c785cSJohn Marino       {
4725c50c785cSJohn Marino 	struct mem_range *r;
4726c50c785cSJohn Marino 	ULONGEST maddr;
4727c50c785cSJohn Marino 	unsigned short mlen;
4728c50c785cSJohn Marino 
4729c50c785cSJohn Marino 	tfile_read ((gdb_byte *) &maddr, 8);
4730*ef5ccd6cSJohn Marino 	maddr = extract_unsigned_integer ((gdb_byte *) &maddr, 8,
4731*ef5ccd6cSJohn Marino 					  gdbarch_byte_order
4732*ef5ccd6cSJohn Marino 					  (target_gdbarch ()));
4733c50c785cSJohn Marino 	tfile_read ((gdb_byte *) &mlen, 2);
4734*ef5ccd6cSJohn Marino 	mlen = (unsigned short)
4735*ef5ccd6cSJohn Marino 		extract_unsigned_integer ((gdb_byte *) &mlen,
4736*ef5ccd6cSJohn Marino 					  2, gdbarch_byte_order
4737*ef5ccd6cSJohn Marino 					  (target_gdbarch ()));
4738c50c785cSJohn Marino 
4739c50c785cSJohn Marino 	r = VEC_safe_push (mem_range_s, info->memory, NULL);
4740c50c785cSJohn Marino 
4741c50c785cSJohn Marino 	r->start = maddr;
4742c50c785cSJohn Marino 	r->length = mlen;
4743c50c785cSJohn Marino 	break;
4744c50c785cSJohn Marino       }
4745c50c785cSJohn Marino     case 'V':
4746c50c785cSJohn Marino     case 'R':
4747c50c785cSJohn Marino     case 'S':
4748c50c785cSJohn Marino       {
4749c50c785cSJohn Marino 	break;
4750c50c785cSJohn Marino       }
4751c50c785cSJohn Marino     default:
4752c50c785cSJohn Marino       warning (_("Unhandled trace block type (%d) '%c ' "
4753c50c785cSJohn Marino 		 "while building trace frame info."),
4754c50c785cSJohn Marino 	       blocktype, blocktype);
4755c50c785cSJohn Marino       break;
4756c50c785cSJohn Marino     }
4757c50c785cSJohn Marino 
4758c50c785cSJohn Marino   return 0;
4759c50c785cSJohn Marino }
4760c50c785cSJohn Marino 
4761c50c785cSJohn Marino static struct traceframe_info *
tfile_traceframe_info(void)4762c50c785cSJohn Marino tfile_traceframe_info (void)
4763c50c785cSJohn Marino {
4764c50c785cSJohn Marino   struct traceframe_info *info = XCNEW (struct traceframe_info);
4765c50c785cSJohn Marino 
4766c50c785cSJohn Marino   traceframe_walk_blocks (build_traceframe_info, 0, info);
4767c50c785cSJohn Marino   return info;
4768c50c785cSJohn Marino }
4769c50c785cSJohn Marino 
4770cf7f2e2dSJohn Marino static void
init_tfile_ops(void)4771cf7f2e2dSJohn Marino init_tfile_ops (void)
4772cf7f2e2dSJohn Marino {
4773cf7f2e2dSJohn Marino   tfile_ops.to_shortname = "tfile";
4774cf7f2e2dSJohn Marino   tfile_ops.to_longname = "Local trace dump file";
4775c50c785cSJohn Marino   tfile_ops.to_doc
4776c50c785cSJohn Marino     = "Use a trace file as a target.  Specify the filename of the trace file.";
4777cf7f2e2dSJohn Marino   tfile_ops.to_open = tfile_open;
4778cf7f2e2dSJohn Marino   tfile_ops.to_close = tfile_close;
4779cf7f2e2dSJohn Marino   tfile_ops.to_fetch_registers = tfile_fetch_registers;
4780cf7f2e2dSJohn Marino   tfile_ops.to_xfer_partial = tfile_xfer_partial;
4781cf7f2e2dSJohn Marino   tfile_ops.to_files_info = tfile_files_info;
4782cf7f2e2dSJohn Marino   tfile_ops.to_get_trace_status = tfile_get_trace_status;
4783a45ae5f8SJohn Marino   tfile_ops.to_get_tracepoint_status = tfile_get_tracepoint_status;
4784cf7f2e2dSJohn Marino   tfile_ops.to_trace_find = tfile_trace_find;
4785c50c785cSJohn Marino   tfile_ops.to_get_trace_state_variable_value
4786c50c785cSJohn Marino     = tfile_get_trace_state_variable_value;
4787cf7f2e2dSJohn Marino   tfile_ops.to_stratum = process_stratum;
4788cf7f2e2dSJohn Marino   tfile_ops.to_has_all_memory = tfile_has_all_memory;
4789cf7f2e2dSJohn Marino   tfile_ops.to_has_memory = tfile_has_memory;
4790cf7f2e2dSJohn Marino   tfile_ops.to_has_stack = tfile_has_stack;
4791cf7f2e2dSJohn Marino   tfile_ops.to_has_registers = tfile_has_registers;
4792c50c785cSJohn Marino   tfile_ops.to_traceframe_info = tfile_traceframe_info;
4793c50c785cSJohn Marino   tfile_ops.to_thread_alive = tfile_thread_alive;
4794cf7f2e2dSJohn Marino   tfile_ops.to_magic = OPS_MAGIC;
4795cf7f2e2dSJohn Marino }
4796cf7f2e2dSJohn Marino 
4797*ef5ccd6cSJohn Marino void
free_current_marker(void * arg)4798*ef5ccd6cSJohn Marino free_current_marker (void *arg)
4799*ef5ccd6cSJohn Marino {
4800*ef5ccd6cSJohn Marino   struct static_tracepoint_marker **marker_p = arg;
4801*ef5ccd6cSJohn Marino 
4802*ef5ccd6cSJohn Marino   if (*marker_p != NULL)
4803*ef5ccd6cSJohn Marino     {
4804*ef5ccd6cSJohn Marino       release_static_tracepoint_marker (*marker_p);
4805*ef5ccd6cSJohn Marino       xfree (*marker_p);
4806*ef5ccd6cSJohn Marino     }
4807*ef5ccd6cSJohn Marino   else
4808*ef5ccd6cSJohn Marino     *marker_p = NULL;
4809*ef5ccd6cSJohn Marino }
4810*ef5ccd6cSJohn Marino 
4811cf7f2e2dSJohn Marino /* Given a line of text defining a static tracepoint marker, parse it
4812cf7f2e2dSJohn Marino    into a "static tracepoint marker" object.  Throws an error is
4813cf7f2e2dSJohn Marino    parsing fails.  If PP is non-null, it points to one past the end of
4814cf7f2e2dSJohn Marino    the parsed marker definition.  */
4815cf7f2e2dSJohn Marino 
4816cf7f2e2dSJohn Marino void
parse_static_tracepoint_marker_definition(char * line,char ** pp,struct static_tracepoint_marker * marker)4817cf7f2e2dSJohn Marino parse_static_tracepoint_marker_definition (char *line, char **pp,
4818cf7f2e2dSJohn Marino 					   struct static_tracepoint_marker *marker)
4819cf7f2e2dSJohn Marino {
4820cf7f2e2dSJohn Marino   char *p, *endp;
4821cf7f2e2dSJohn Marino   ULONGEST addr;
4822cf7f2e2dSJohn Marino   int end;
4823cf7f2e2dSJohn Marino 
4824cf7f2e2dSJohn Marino   p = line;
4825cf7f2e2dSJohn Marino   p = unpack_varlen_hex (p, &addr);
4826cf7f2e2dSJohn Marino   p++;  /* skip a colon */
4827cf7f2e2dSJohn Marino 
4828*ef5ccd6cSJohn Marino   marker->gdbarch = target_gdbarch ();
4829cf7f2e2dSJohn Marino   marker->address = (CORE_ADDR) addr;
4830cf7f2e2dSJohn Marino 
4831cf7f2e2dSJohn Marino   endp = strchr (p, ':');
4832cf7f2e2dSJohn Marino   if (endp == NULL)
4833c50c785cSJohn Marino     error (_("bad marker definition: %s"), line);
4834cf7f2e2dSJohn Marino 
4835cf7f2e2dSJohn Marino   marker->str_id = xmalloc (endp - p + 1);
4836cf7f2e2dSJohn Marino   end = hex2bin (p, (gdb_byte *) marker->str_id, (endp - p + 1) / 2);
4837cf7f2e2dSJohn Marino   marker->str_id[end] = '\0';
4838cf7f2e2dSJohn Marino 
4839cf7f2e2dSJohn Marino   p += 2 * end;
4840cf7f2e2dSJohn Marino   p++;  /* skip a colon */
4841cf7f2e2dSJohn Marino 
4842cf7f2e2dSJohn Marino   marker->extra = xmalloc (strlen (p) + 1);
4843cf7f2e2dSJohn Marino   end = hex2bin (p, (gdb_byte *) marker->extra, strlen (p) / 2);
4844cf7f2e2dSJohn Marino   marker->extra[end] = '\0';
4845cf7f2e2dSJohn Marino 
4846cf7f2e2dSJohn Marino   if (pp)
4847cf7f2e2dSJohn Marino     *pp = p;
4848cf7f2e2dSJohn Marino }
4849cf7f2e2dSJohn Marino 
4850cf7f2e2dSJohn Marino /* Release a static tracepoint marker's contents.  Note that the
4851cf7f2e2dSJohn Marino    object itself isn't released here.  There objects are usually on
4852cf7f2e2dSJohn Marino    the stack.  */
4853cf7f2e2dSJohn Marino 
4854cf7f2e2dSJohn Marino void
release_static_tracepoint_marker(struct static_tracepoint_marker * marker)4855cf7f2e2dSJohn Marino release_static_tracepoint_marker (struct static_tracepoint_marker *marker)
4856cf7f2e2dSJohn Marino {
4857cf7f2e2dSJohn Marino   xfree (marker->str_id);
4858cf7f2e2dSJohn Marino   marker->str_id = NULL;
4859cf7f2e2dSJohn Marino }
4860cf7f2e2dSJohn Marino 
4861cf7f2e2dSJohn Marino /* Print MARKER to gdb_stdout.  */
4862cf7f2e2dSJohn Marino 
4863cf7f2e2dSJohn Marino static void
print_one_static_tracepoint_marker(int count,struct static_tracepoint_marker * marker)4864cf7f2e2dSJohn Marino print_one_static_tracepoint_marker (int count,
4865cf7f2e2dSJohn Marino 				    struct static_tracepoint_marker *marker)
4866cf7f2e2dSJohn Marino {
4867cf7f2e2dSJohn Marino   struct command_line *l;
4868cf7f2e2dSJohn Marino   struct symbol *sym;
4869cf7f2e2dSJohn Marino 
4870cf7f2e2dSJohn Marino   char wrap_indent[80];
4871cf7f2e2dSJohn Marino   char extra_field_indent[80];
4872a45ae5f8SJohn Marino   struct ui_out *uiout = current_uiout;
4873cf7f2e2dSJohn Marino   struct cleanup *bkpt_chain;
4874cf7f2e2dSJohn Marino   VEC(breakpoint_p) *tracepoints;
4875cf7f2e2dSJohn Marino 
4876cf7f2e2dSJohn Marino   struct symtab_and_line sal;
4877cf7f2e2dSJohn Marino 
4878cf7f2e2dSJohn Marino   init_sal (&sal);
4879cf7f2e2dSJohn Marino 
4880cf7f2e2dSJohn Marino   sal.pc = marker->address;
4881cf7f2e2dSJohn Marino 
4882cf7f2e2dSJohn Marino   tracepoints = static_tracepoints_here (marker->address);
4883cf7f2e2dSJohn Marino 
4884cf7f2e2dSJohn Marino   bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "marker");
4885cf7f2e2dSJohn Marino 
4886cf7f2e2dSJohn Marino   /* A counter field to help readability.  This is not a stable
4887cf7f2e2dSJohn Marino      identifier!  */
4888cf7f2e2dSJohn Marino   ui_out_field_int (uiout, "count", count);
4889cf7f2e2dSJohn Marino 
4890cf7f2e2dSJohn Marino   ui_out_field_string (uiout, "marker-id", marker->str_id);
4891cf7f2e2dSJohn Marino 
4892cf7f2e2dSJohn Marino   ui_out_field_fmt (uiout, "enabled", "%c",
4893cf7f2e2dSJohn Marino 		    !VEC_empty (breakpoint_p, tracepoints) ? 'y' : 'n');
4894cf7f2e2dSJohn Marino   ui_out_spaces (uiout, 2);
4895cf7f2e2dSJohn Marino 
4896cf7f2e2dSJohn Marino   strcpy (wrap_indent, "                                   ");
4897cf7f2e2dSJohn Marino 
4898cf7f2e2dSJohn Marino   if (gdbarch_addr_bit (marker->gdbarch) <= 32)
4899cf7f2e2dSJohn Marino     strcat (wrap_indent, "           ");
4900cf7f2e2dSJohn Marino   else
4901cf7f2e2dSJohn Marino     strcat (wrap_indent, "                   ");
4902cf7f2e2dSJohn Marino 
4903cf7f2e2dSJohn Marino   strcpy (extra_field_indent, "         ");
4904cf7f2e2dSJohn Marino 
4905cf7f2e2dSJohn Marino   ui_out_field_core_addr (uiout, "addr", marker->gdbarch, marker->address);
4906cf7f2e2dSJohn Marino 
4907cf7f2e2dSJohn Marino   sal = find_pc_line (marker->address, 0);
4908cf7f2e2dSJohn Marino   sym = find_pc_sect_function (marker->address, NULL);
4909cf7f2e2dSJohn Marino   if (sym)
4910cf7f2e2dSJohn Marino     {
4911cf7f2e2dSJohn Marino       ui_out_text (uiout, "in ");
4912cf7f2e2dSJohn Marino       ui_out_field_string (uiout, "func",
4913cf7f2e2dSJohn Marino 			   SYMBOL_PRINT_NAME (sym));
4914cf7f2e2dSJohn Marino       ui_out_wrap_hint (uiout, wrap_indent);
4915cf7f2e2dSJohn Marino       ui_out_text (uiout, " at ");
4916cf7f2e2dSJohn Marino     }
4917cf7f2e2dSJohn Marino   else
4918cf7f2e2dSJohn Marino     ui_out_field_skip (uiout, "func");
4919cf7f2e2dSJohn Marino 
4920cf7f2e2dSJohn Marino   if (sal.symtab != NULL)
4921cf7f2e2dSJohn Marino     {
4922*ef5ccd6cSJohn Marino       ui_out_field_string (uiout, "file",
4923*ef5ccd6cSJohn Marino 			   symtab_to_filename_for_display (sal.symtab));
4924cf7f2e2dSJohn Marino       ui_out_text (uiout, ":");
4925cf7f2e2dSJohn Marino 
4926cf7f2e2dSJohn Marino       if (ui_out_is_mi_like_p (uiout))
4927cf7f2e2dSJohn Marino 	{
4928*ef5ccd6cSJohn Marino 	  const char *fullname = symtab_to_fullname (sal.symtab);
4929cf7f2e2dSJohn Marino 
4930cf7f2e2dSJohn Marino 	  ui_out_field_string (uiout, "fullname", fullname);
4931cf7f2e2dSJohn Marino 	}
4932cf7f2e2dSJohn Marino       else
4933cf7f2e2dSJohn Marino 	ui_out_field_skip (uiout, "fullname");
4934cf7f2e2dSJohn Marino 
4935cf7f2e2dSJohn Marino       ui_out_field_int (uiout, "line", sal.line);
4936cf7f2e2dSJohn Marino     }
4937cf7f2e2dSJohn Marino   else
4938cf7f2e2dSJohn Marino     {
4939cf7f2e2dSJohn Marino       ui_out_field_skip (uiout, "fullname");
4940cf7f2e2dSJohn Marino       ui_out_field_skip (uiout, "line");
4941cf7f2e2dSJohn Marino     }
4942cf7f2e2dSJohn Marino 
4943cf7f2e2dSJohn Marino   ui_out_text (uiout, "\n");
4944cf7f2e2dSJohn Marino   ui_out_text (uiout, extra_field_indent);
4945cf7f2e2dSJohn Marino   ui_out_text (uiout, _("Data: \""));
4946cf7f2e2dSJohn Marino   ui_out_field_string (uiout, "extra-data", marker->extra);
4947cf7f2e2dSJohn Marino   ui_out_text (uiout, "\"\n");
4948cf7f2e2dSJohn Marino 
4949cf7f2e2dSJohn Marino   if (!VEC_empty (breakpoint_p, tracepoints))
4950cf7f2e2dSJohn Marino     {
4951cf7f2e2dSJohn Marino       struct cleanup *cleanup_chain;
4952cf7f2e2dSJohn Marino       int ix;
4953cf7f2e2dSJohn Marino       struct breakpoint *b;
4954cf7f2e2dSJohn Marino 
4955cf7f2e2dSJohn Marino       cleanup_chain = make_cleanup_ui_out_tuple_begin_end (uiout,
4956cf7f2e2dSJohn Marino 							   "tracepoints-at");
4957cf7f2e2dSJohn Marino 
4958cf7f2e2dSJohn Marino       ui_out_text (uiout, extra_field_indent);
4959cf7f2e2dSJohn Marino       ui_out_text (uiout, _("Probed by static tracepoints: "));
4960cf7f2e2dSJohn Marino       for (ix = 0; VEC_iterate(breakpoint_p, tracepoints, ix, b); ix++)
4961cf7f2e2dSJohn Marino 	{
4962cf7f2e2dSJohn Marino 	  if (ix > 0)
4963cf7f2e2dSJohn Marino 	    ui_out_text (uiout, ", ");
4964cf7f2e2dSJohn Marino 	  ui_out_text (uiout, "#");
4965cf7f2e2dSJohn Marino 	  ui_out_field_int (uiout, "tracepoint-id", b->number);
4966cf7f2e2dSJohn Marino 	}
4967cf7f2e2dSJohn Marino 
4968cf7f2e2dSJohn Marino       do_cleanups (cleanup_chain);
4969cf7f2e2dSJohn Marino 
4970cf7f2e2dSJohn Marino       if (ui_out_is_mi_like_p (uiout))
4971cf7f2e2dSJohn Marino 	ui_out_field_int (uiout, "number-of-tracepoints",
4972cf7f2e2dSJohn Marino 			  VEC_length(breakpoint_p, tracepoints));
4973cf7f2e2dSJohn Marino       else
4974cf7f2e2dSJohn Marino 	ui_out_text (uiout, "\n");
4975cf7f2e2dSJohn Marino     }
4976cf7f2e2dSJohn Marino   VEC_free (breakpoint_p, tracepoints);
4977cf7f2e2dSJohn Marino 
4978cf7f2e2dSJohn Marino   do_cleanups (bkpt_chain);
4979cf7f2e2dSJohn Marino }
4980cf7f2e2dSJohn Marino 
4981cf7f2e2dSJohn Marino static void
info_static_tracepoint_markers_command(char * arg,int from_tty)4982cf7f2e2dSJohn Marino info_static_tracepoint_markers_command (char *arg, int from_tty)
4983cf7f2e2dSJohn Marino {
4984cf7f2e2dSJohn Marino   VEC(static_tracepoint_marker_p) *markers;
4985cf7f2e2dSJohn Marino   struct cleanup *old_chain;
4986cf7f2e2dSJohn Marino   struct static_tracepoint_marker *marker;
4987a45ae5f8SJohn Marino   struct ui_out *uiout = current_uiout;
4988cf7f2e2dSJohn Marino   int i;
4989cf7f2e2dSJohn Marino 
4990*ef5ccd6cSJohn Marino   /* We don't have to check target_can_use_agent and agent's capability on
4991*ef5ccd6cSJohn Marino      static tracepoint here, in order to be compatible with older GDBserver.
4992*ef5ccd6cSJohn Marino      We don't check USE_AGENT is true or not, because static tracepoints
4993*ef5ccd6cSJohn Marino      don't work without in-process agent, so we don't bother users to type
4994*ef5ccd6cSJohn Marino      `set agent on' when to use static tracepoint.  */
4995*ef5ccd6cSJohn Marino 
4996cf7f2e2dSJohn Marino   old_chain
4997cf7f2e2dSJohn Marino     = make_cleanup_ui_out_table_begin_end (uiout, 5, -1,
4998cf7f2e2dSJohn Marino 					   "StaticTracepointMarkersTable");
4999cf7f2e2dSJohn Marino 
5000cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 7, ui_left, "counter", "Cnt");
5001cf7f2e2dSJohn Marino 
5002cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 40, ui_left, "marker-id", "ID");
5003cf7f2e2dSJohn Marino 
5004cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb");
5005*ef5ccd6cSJohn Marino   if (gdbarch_addr_bit (target_gdbarch ()) <= 32)
5006cf7f2e2dSJohn Marino     ui_out_table_header (uiout, 10, ui_left, "addr", "Address");
5007cf7f2e2dSJohn Marino   else
5008cf7f2e2dSJohn Marino     ui_out_table_header (uiout, 18, ui_left, "addr", "Address");
5009cf7f2e2dSJohn Marino   ui_out_table_header (uiout, 40, ui_noalign, "what", "What");
5010cf7f2e2dSJohn Marino 
5011cf7f2e2dSJohn Marino   ui_out_table_body (uiout);
5012cf7f2e2dSJohn Marino 
5013cf7f2e2dSJohn Marino   markers = target_static_tracepoint_markers_by_strid (NULL);
5014cf7f2e2dSJohn Marino   make_cleanup (VEC_cleanup (static_tracepoint_marker_p), &markers);
5015cf7f2e2dSJohn Marino 
5016cf7f2e2dSJohn Marino   for (i = 0;
5017cf7f2e2dSJohn Marino        VEC_iterate (static_tracepoint_marker_p,
5018cf7f2e2dSJohn Marino 		    markers, i, marker);
5019cf7f2e2dSJohn Marino        i++)
5020cf7f2e2dSJohn Marino     {
5021cf7f2e2dSJohn Marino       print_one_static_tracepoint_marker (i + 1, marker);
5022cf7f2e2dSJohn Marino       release_static_tracepoint_marker (marker);
5023cf7f2e2dSJohn Marino     }
5024cf7f2e2dSJohn Marino 
5025cf7f2e2dSJohn Marino   do_cleanups (old_chain);
5026cf7f2e2dSJohn Marino }
5027cf7f2e2dSJohn Marino 
5028cf7f2e2dSJohn Marino /* The $_sdata convenience variable is a bit special.  We don't know
5029cf7f2e2dSJohn Marino    for sure type of the value until we actually have a chance to fetch
5030cf7f2e2dSJohn Marino    the data --- the size of the object depends on what has been
5031cf7f2e2dSJohn Marino    collected.  We solve this by making $_sdata be an internalvar that
5032cf7f2e2dSJohn Marino    creates a new value on access.  */
5033cf7f2e2dSJohn Marino 
5034cf7f2e2dSJohn Marino /* Return a new value with the correct type for the sdata object of
5035cf7f2e2dSJohn Marino    the current trace frame.  Return a void value if there's no object
5036cf7f2e2dSJohn Marino    available.  */
5037cf7f2e2dSJohn Marino 
5038cf7f2e2dSJohn Marino static struct value *
sdata_make_value(struct gdbarch * gdbarch,struct internalvar * var,void * ignore)5039*ef5ccd6cSJohn Marino sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var,
5040*ef5ccd6cSJohn Marino 		  void *ignore)
5041cf7f2e2dSJohn Marino {
5042cf7f2e2dSJohn Marino   LONGEST size;
5043cf7f2e2dSJohn Marino   gdb_byte *buf;
5044cf7f2e2dSJohn Marino 
5045cf7f2e2dSJohn Marino   /* We need to read the whole object before we know its size.  */
5046cf7f2e2dSJohn Marino   size = target_read_alloc (&current_target,
5047cf7f2e2dSJohn Marino 			    TARGET_OBJECT_STATIC_TRACE_DATA,
5048cf7f2e2dSJohn Marino 			    NULL, &buf);
5049cf7f2e2dSJohn Marino   if (size >= 0)
5050cf7f2e2dSJohn Marino     {
5051cf7f2e2dSJohn Marino       struct value *v;
5052cf7f2e2dSJohn Marino       struct type *type;
5053cf7f2e2dSJohn Marino 
5054cf7f2e2dSJohn Marino       type = init_vector_type (builtin_type (gdbarch)->builtin_true_char,
5055cf7f2e2dSJohn Marino 			       size);
5056cf7f2e2dSJohn Marino       v = allocate_value (type);
5057cf7f2e2dSJohn Marino       memcpy (value_contents_raw (v), buf, size);
5058cf7f2e2dSJohn Marino       xfree (buf);
5059cf7f2e2dSJohn Marino       return v;
5060cf7f2e2dSJohn Marino     }
5061cf7f2e2dSJohn Marino   else
5062cf7f2e2dSJohn Marino     return allocate_value (builtin_type (gdbarch)->builtin_void);
5063cf7f2e2dSJohn Marino }
50645796c8dcSSimon Schubert 
5065c50c785cSJohn Marino #if !defined(HAVE_LIBEXPAT)
5066c50c785cSJohn Marino 
5067c50c785cSJohn Marino struct traceframe_info *
parse_traceframe_info(const char * tframe_info)5068c50c785cSJohn Marino parse_traceframe_info (const char *tframe_info)
5069c50c785cSJohn Marino {
5070c50c785cSJohn Marino   static int have_warned;
5071c50c785cSJohn Marino 
5072c50c785cSJohn Marino   if (!have_warned)
5073c50c785cSJohn Marino     {
5074c50c785cSJohn Marino       have_warned = 1;
5075c50c785cSJohn Marino       warning (_("Can not parse XML trace frame info; XML support "
5076c50c785cSJohn Marino 		 "was disabled at compile time"));
5077c50c785cSJohn Marino     }
5078c50c785cSJohn Marino 
5079c50c785cSJohn Marino   return NULL;
5080c50c785cSJohn Marino }
5081c50c785cSJohn Marino 
5082c50c785cSJohn Marino #else /* HAVE_LIBEXPAT */
5083c50c785cSJohn Marino 
5084c50c785cSJohn Marino #include "xml-support.h"
5085c50c785cSJohn Marino 
5086c50c785cSJohn Marino /* Handle the start of a <memory> element.  */
5087c50c785cSJohn Marino 
5088c50c785cSJohn Marino static void
traceframe_info_start_memory(struct gdb_xml_parser * parser,const struct gdb_xml_element * element,void * user_data,VEC (gdb_xml_value_s)* attributes)5089c50c785cSJohn Marino traceframe_info_start_memory (struct gdb_xml_parser *parser,
5090c50c785cSJohn Marino 			      const struct gdb_xml_element *element,
5091c50c785cSJohn Marino 			      void *user_data, VEC(gdb_xml_value_s) *attributes)
5092c50c785cSJohn Marino {
5093c50c785cSJohn Marino   struct traceframe_info *info = user_data;
5094c50c785cSJohn Marino   struct mem_range *r = VEC_safe_push (mem_range_s, info->memory, NULL);
5095c50c785cSJohn Marino   ULONGEST *start_p, *length_p;
5096c50c785cSJohn Marino 
5097c50c785cSJohn Marino   start_p = xml_find_attribute (attributes, "start")->value;
5098c50c785cSJohn Marino   length_p = xml_find_attribute (attributes, "length")->value;
5099c50c785cSJohn Marino 
5100c50c785cSJohn Marino   r->start = *start_p;
5101c50c785cSJohn Marino   r->length = *length_p;
5102c50c785cSJohn Marino }
5103c50c785cSJohn Marino 
5104c50c785cSJohn Marino /* Discard the constructed trace frame info (if an error occurs).  */
5105c50c785cSJohn Marino 
5106c50c785cSJohn Marino static void
free_result(void * p)5107c50c785cSJohn Marino free_result (void *p)
5108c50c785cSJohn Marino {
5109c50c785cSJohn Marino   struct traceframe_info *result = p;
5110c50c785cSJohn Marino 
5111c50c785cSJohn Marino   free_traceframe_info (result);
5112c50c785cSJohn Marino }
5113c50c785cSJohn Marino 
5114c50c785cSJohn Marino /* The allowed elements and attributes for an XML memory map.  */
5115c50c785cSJohn Marino 
5116c50c785cSJohn Marino static const struct gdb_xml_attribute memory_attributes[] = {
5117c50c785cSJohn Marino   { "start", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
5118c50c785cSJohn Marino   { "length", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
5119c50c785cSJohn Marino   { NULL, GDB_XML_AF_NONE, NULL, NULL }
5120c50c785cSJohn Marino };
5121c50c785cSJohn Marino 
5122c50c785cSJohn Marino static const struct gdb_xml_element traceframe_info_children[] = {
5123c50c785cSJohn Marino   { "memory", memory_attributes, NULL,
5124c50c785cSJohn Marino     GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
5125c50c785cSJohn Marino     traceframe_info_start_memory, NULL },
5126c50c785cSJohn Marino   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
5127c50c785cSJohn Marino };
5128c50c785cSJohn Marino 
5129c50c785cSJohn Marino static const struct gdb_xml_element traceframe_info_elements[] = {
5130c50c785cSJohn Marino   { "traceframe-info", NULL, traceframe_info_children, GDB_XML_EF_NONE,
5131c50c785cSJohn Marino     NULL, NULL },
5132c50c785cSJohn Marino   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
5133c50c785cSJohn Marino };
5134c50c785cSJohn Marino 
5135c50c785cSJohn Marino /* Parse a traceframe-info XML document.  */
5136c50c785cSJohn Marino 
5137c50c785cSJohn Marino struct traceframe_info *
parse_traceframe_info(const char * tframe_info)5138c50c785cSJohn Marino parse_traceframe_info (const char *tframe_info)
5139c50c785cSJohn Marino {
5140c50c785cSJohn Marino   struct traceframe_info *result;
5141c50c785cSJohn Marino   struct cleanup *back_to;
5142c50c785cSJohn Marino 
5143c50c785cSJohn Marino   result = XCNEW (struct traceframe_info);
5144c50c785cSJohn Marino   back_to = make_cleanup (free_result, result);
5145c50c785cSJohn Marino 
5146c50c785cSJohn Marino   if (gdb_xml_parse_quick (_("trace frame info"),
5147c50c785cSJohn Marino 			   "traceframe-info.dtd", traceframe_info_elements,
5148c50c785cSJohn Marino 			   tframe_info, result) == 0)
5149c50c785cSJohn Marino     {
5150c50c785cSJohn Marino       /* Parsed successfully, keep the result.  */
5151c50c785cSJohn Marino       discard_cleanups (back_to);
5152c50c785cSJohn Marino 
5153c50c785cSJohn Marino       return result;
5154c50c785cSJohn Marino     }
5155c50c785cSJohn Marino 
5156c50c785cSJohn Marino   do_cleanups (back_to);
5157c50c785cSJohn Marino   return NULL;
5158c50c785cSJohn Marino }
5159c50c785cSJohn Marino 
5160c50c785cSJohn Marino #endif /* HAVE_LIBEXPAT */
5161c50c785cSJohn Marino 
5162c50c785cSJohn Marino /* Returns the traceframe_info object for the current traceframe.
5163c50c785cSJohn Marino    This is where we avoid re-fetching the object from the target if we
5164c50c785cSJohn Marino    already have it cached.  */
5165c50c785cSJohn Marino 
5166*ef5ccd6cSJohn Marino static struct traceframe_info *
get_traceframe_info(void)5167c50c785cSJohn Marino get_traceframe_info (void)
5168c50c785cSJohn Marino {
5169c50c785cSJohn Marino   if (traceframe_info == NULL)
5170c50c785cSJohn Marino     traceframe_info = target_traceframe_info ();
5171c50c785cSJohn Marino 
5172c50c785cSJohn Marino   return traceframe_info;
5173c50c785cSJohn Marino }
5174c50c785cSJohn Marino 
5175c50c785cSJohn Marino /* If the target supports the query, return in RESULT the set of
5176c50c785cSJohn Marino    collected memory in the current traceframe, found within the LEN
5177c50c785cSJohn Marino    bytes range starting at MEMADDR.  Returns true if the target
5178c50c785cSJohn Marino    supports the query, otherwise returns false, and RESULT is left
5179c50c785cSJohn Marino    undefined.  */
5180c50c785cSJohn Marino 
5181c50c785cSJohn Marino int
traceframe_available_memory(VEC (mem_range_s)** result,CORE_ADDR memaddr,ULONGEST len)5182c50c785cSJohn Marino traceframe_available_memory (VEC(mem_range_s) **result,
5183c50c785cSJohn Marino 			     CORE_ADDR memaddr, ULONGEST len)
5184c50c785cSJohn Marino {
5185c50c785cSJohn Marino   struct traceframe_info *info = get_traceframe_info ();
5186c50c785cSJohn Marino 
5187c50c785cSJohn Marino   if (info != NULL)
5188c50c785cSJohn Marino     {
5189c50c785cSJohn Marino       struct mem_range *r;
5190c50c785cSJohn Marino       int i;
5191c50c785cSJohn Marino 
5192c50c785cSJohn Marino       *result = NULL;
5193c50c785cSJohn Marino 
5194c50c785cSJohn Marino       for (i = 0; VEC_iterate (mem_range_s, info->memory, i, r); i++)
5195c50c785cSJohn Marino 	if (mem_ranges_overlap (r->start, r->length, memaddr, len))
5196c50c785cSJohn Marino 	  {
5197c50c785cSJohn Marino 	    ULONGEST lo1, hi1, lo2, hi2;
5198c50c785cSJohn Marino 	    struct mem_range *nr;
5199c50c785cSJohn Marino 
5200c50c785cSJohn Marino 	    lo1 = memaddr;
5201c50c785cSJohn Marino 	    hi1 = memaddr + len;
5202c50c785cSJohn Marino 
5203c50c785cSJohn Marino 	    lo2 = r->start;
5204c50c785cSJohn Marino 	    hi2 = r->start + r->length;
5205c50c785cSJohn Marino 
5206c50c785cSJohn Marino 	    nr = VEC_safe_push (mem_range_s, *result, NULL);
5207c50c785cSJohn Marino 
5208c50c785cSJohn Marino 	    nr->start = max (lo1, lo2);
5209c50c785cSJohn Marino 	    nr->length = min (hi1, hi2) - nr->start;
5210c50c785cSJohn Marino 	  }
5211c50c785cSJohn Marino 
5212c50c785cSJohn Marino       normalize_mem_ranges (*result);
5213c50c785cSJohn Marino       return 1;
5214c50c785cSJohn Marino     }
5215c50c785cSJohn Marino 
5216c50c785cSJohn Marino   return 0;
5217c50c785cSJohn Marino }
5218c50c785cSJohn Marino 
5219*ef5ccd6cSJohn Marino /* Implementation of `sdata' variable.  */
5220*ef5ccd6cSJohn Marino 
5221*ef5ccd6cSJohn Marino static const struct internalvar_funcs sdata_funcs =
5222*ef5ccd6cSJohn Marino {
5223*ef5ccd6cSJohn Marino   sdata_make_value,
5224*ef5ccd6cSJohn Marino   NULL,
5225*ef5ccd6cSJohn Marino   NULL
5226*ef5ccd6cSJohn Marino };
5227*ef5ccd6cSJohn Marino 
52285796c8dcSSimon Schubert /* module initialization */
52295796c8dcSSimon Schubert void
_initialize_tracepoint(void)52305796c8dcSSimon Schubert _initialize_tracepoint (void)
52315796c8dcSSimon Schubert {
52325796c8dcSSimon Schubert   struct cmd_list_element *c;
52335796c8dcSSimon Schubert 
5234cf7f2e2dSJohn Marino   /* Explicitly create without lookup, since that tries to create a
5235cf7f2e2dSJohn Marino      value with a void typed value, and when we get here, gdbarch
5236cf7f2e2dSJohn Marino      isn't initialized yet.  At this point, we're quite sure there
5237cf7f2e2dSJohn Marino      isn't another convenience variable of the same name.  */
5238*ef5ccd6cSJohn Marino   create_internalvar_type_lazy ("_sdata", &sdata_funcs, NULL);
5239cf7f2e2dSJohn Marino 
52405796c8dcSSimon Schubert   traceframe_number = -1;
52415796c8dcSSimon Schubert   tracepoint_number = -1;
52425796c8dcSSimon Schubert 
52435796c8dcSSimon Schubert   if (tracepoint_list.list == NULL)
52445796c8dcSSimon Schubert     {
52455796c8dcSSimon Schubert       tracepoint_list.listsize = 128;
52465796c8dcSSimon Schubert       tracepoint_list.list = xmalloc
52475796c8dcSSimon Schubert 	(tracepoint_list.listsize * sizeof (struct memrange));
52485796c8dcSSimon Schubert     }
52495796c8dcSSimon Schubert   if (tracepoint_list.aexpr_list == NULL)
52505796c8dcSSimon Schubert     {
52515796c8dcSSimon Schubert       tracepoint_list.aexpr_listsize = 128;
52525796c8dcSSimon Schubert       tracepoint_list.aexpr_list = xmalloc
52535796c8dcSSimon Schubert 	(tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *));
52545796c8dcSSimon Schubert     }
52555796c8dcSSimon Schubert 
52565796c8dcSSimon Schubert   if (stepping_list.list == NULL)
52575796c8dcSSimon Schubert     {
52585796c8dcSSimon Schubert       stepping_list.listsize = 128;
52595796c8dcSSimon Schubert       stepping_list.list = xmalloc
52605796c8dcSSimon Schubert 	(stepping_list.listsize * sizeof (struct memrange));
52615796c8dcSSimon Schubert     }
52625796c8dcSSimon Schubert 
52635796c8dcSSimon Schubert   if (stepping_list.aexpr_list == NULL)
52645796c8dcSSimon Schubert     {
52655796c8dcSSimon Schubert       stepping_list.aexpr_listsize = 128;
52665796c8dcSSimon Schubert       stepping_list.aexpr_list = xmalloc
52675796c8dcSSimon Schubert 	(stepping_list.aexpr_listsize * sizeof (struct agent_expr *));
52685796c8dcSSimon Schubert     }
52695796c8dcSSimon Schubert 
52705796c8dcSSimon Schubert   add_info ("scope", scope_info,
52715796c8dcSSimon Schubert 	    _("List the variables local to a scope"));
52725796c8dcSSimon Schubert 
52735796c8dcSSimon Schubert   add_cmd ("tracepoints", class_trace, NULL,
52745796c8dcSSimon Schubert 	   _("Tracing of program execution without stopping the program."),
52755796c8dcSSimon Schubert 	   &cmdlist);
52765796c8dcSSimon Schubert 
52775796c8dcSSimon Schubert   add_com ("tdump", class_trace, trace_dump_command,
52785796c8dcSSimon Schubert 	   _("Print everything collected at the current tracepoint."));
52795796c8dcSSimon Schubert 
5280cf7f2e2dSJohn Marino   add_com ("tsave", class_trace, trace_save_command, _("\
5281cf7f2e2dSJohn Marino Save the trace data to a file.\n\
5282cf7f2e2dSJohn Marino Use the '-r' option to direct the target to save directly to the file,\n\
5283cf7f2e2dSJohn Marino using its own filesystem."));
5284cf7f2e2dSJohn Marino 
5285cf7f2e2dSJohn Marino   c = add_com ("tvariable", class_trace, trace_variable_command,_("\
5286cf7f2e2dSJohn Marino Define a trace state variable.\n\
5287cf7f2e2dSJohn Marino Argument is a $-prefixed name, optionally followed\n\
5288cf7f2e2dSJohn Marino by '=' and an expression that sets the initial value\n\
5289cf7f2e2dSJohn Marino at the start of tracing."));
5290cf7f2e2dSJohn Marino   set_cmd_completer (c, expression_completer);
5291cf7f2e2dSJohn Marino 
5292cf7f2e2dSJohn Marino   add_cmd ("tvariable", class_trace, delete_trace_variable_command, _("\
5293cf7f2e2dSJohn Marino Delete one or more trace state variables.\n\
5294cf7f2e2dSJohn Marino Arguments are the names of the variables to delete.\n\
5295cf7f2e2dSJohn Marino If no arguments are supplied, delete all variables."), &deletelist);
5296c50c785cSJohn Marino   /* FIXME add a trace variable completer.  */
5297cf7f2e2dSJohn Marino 
5298cf7f2e2dSJohn Marino   add_info ("tvariables", tvariables_info, _("\
5299cf7f2e2dSJohn Marino Status of trace state variables and their values.\n\
5300cf7f2e2dSJohn Marino "));
5301cf7f2e2dSJohn Marino 
5302cf7f2e2dSJohn Marino   add_info ("static-tracepoint-markers",
5303cf7f2e2dSJohn Marino 	    info_static_tracepoint_markers_command, _("\
5304cf7f2e2dSJohn Marino List target static tracepoints markers.\n\
5305cf7f2e2dSJohn Marino "));
5306cf7f2e2dSJohn Marino 
53075796c8dcSSimon Schubert   add_prefix_cmd ("tfind", class_trace, trace_find_command, _("\
53085796c8dcSSimon Schubert Select a trace frame;\n\
53095796c8dcSSimon Schubert No argument means forward by one frame; '-' means backward by one frame."),
53105796c8dcSSimon Schubert 		  &tfindlist, "tfind ", 1, &cmdlist);
53115796c8dcSSimon Schubert 
53125796c8dcSSimon Schubert   add_cmd ("outside", class_trace, trace_find_outside_command, _("\
5313cf7f2e2dSJohn Marino Select a trace frame whose PC is outside the given range (exclusive).\n\
53145796c8dcSSimon Schubert Usage: tfind outside addr1, addr2"),
53155796c8dcSSimon Schubert 	   &tfindlist);
53165796c8dcSSimon Schubert 
53175796c8dcSSimon Schubert   add_cmd ("range", class_trace, trace_find_range_command, _("\
5318cf7f2e2dSJohn Marino Select a trace frame whose PC is in the given range (inclusive).\n\
53195796c8dcSSimon Schubert Usage: tfind range addr1,addr2"),
53205796c8dcSSimon Schubert 	   &tfindlist);
53215796c8dcSSimon Schubert 
53225796c8dcSSimon Schubert   add_cmd ("line", class_trace, trace_find_line_command, _("\
53235796c8dcSSimon Schubert Select a trace frame by source line.\n\
53245796c8dcSSimon Schubert Argument can be a line number (with optional source file),\n\
53255796c8dcSSimon Schubert a function name, or '*' followed by an address.\n\
53265796c8dcSSimon Schubert Default argument is 'the next source line that was traced'."),
53275796c8dcSSimon Schubert 	   &tfindlist);
53285796c8dcSSimon Schubert 
53295796c8dcSSimon Schubert   add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command, _("\
53305796c8dcSSimon Schubert Select a trace frame by tracepoint number.\n\
53315796c8dcSSimon Schubert Default is the tracepoint for the current trace frame."),
53325796c8dcSSimon Schubert 	   &tfindlist);
53335796c8dcSSimon Schubert 
53345796c8dcSSimon Schubert   add_cmd ("pc", class_trace, trace_find_pc_command, _("\
53355796c8dcSSimon Schubert Select a trace frame by PC.\n\
53365796c8dcSSimon Schubert Default is the current PC, or the PC of the current trace frame."),
53375796c8dcSSimon Schubert 	   &tfindlist);
53385796c8dcSSimon Schubert 
53395796c8dcSSimon Schubert   add_cmd ("end", class_trace, trace_find_end_command, _("\
53405796c8dcSSimon Schubert De-select any trace frame and resume 'live' debugging."),
53415796c8dcSSimon Schubert 	   &tfindlist);
53425796c8dcSSimon Schubert 
5343*ef5ccd6cSJohn Marino   add_alias_cmd ("none", "end", class_trace, 0, &tfindlist);
53445796c8dcSSimon Schubert 
53455796c8dcSSimon Schubert   add_cmd ("start", class_trace, trace_find_start_command,
53465796c8dcSSimon Schubert 	   _("Select the first trace frame in the trace buffer."),
53475796c8dcSSimon Schubert 	   &tfindlist);
53485796c8dcSSimon Schubert 
53495796c8dcSSimon Schubert   add_com ("tstatus", class_trace, trace_status_command,
53505796c8dcSSimon Schubert 	   _("Display the status of the current trace data collection."));
53515796c8dcSSimon Schubert 
5352a45ae5f8SJohn Marino   add_com ("tstop", class_trace, trace_stop_command, _("\
5353a45ae5f8SJohn Marino Stop trace data collection.\n\
5354a45ae5f8SJohn Marino Usage: tstop [ <notes> ... ]\n\
5355a45ae5f8SJohn Marino Any arguments supplied are recorded with the trace as a stop reason and\n\
5356a45ae5f8SJohn Marino reported by tstatus (if the target supports trace notes)."));
53575796c8dcSSimon Schubert 
5358a45ae5f8SJohn Marino   add_com ("tstart", class_trace, trace_start_command, _("\
5359a45ae5f8SJohn Marino Start trace data collection.\n\
5360a45ae5f8SJohn Marino Usage: tstart [ <notes> ... ]\n\
5361a45ae5f8SJohn Marino Any arguments supplied are recorded with the trace as a note and\n\
5362a45ae5f8SJohn Marino reported by tstatus (if the target supports trace notes)."));
53635796c8dcSSimon Schubert 
53645796c8dcSSimon Schubert   add_com ("end", class_trace, end_actions_pseudocommand, _("\
53655796c8dcSSimon Schubert Ends a list of commands or actions.\n\
53665796c8dcSSimon Schubert Several GDB commands allow you to enter a list of commands or actions.\n\
53675796c8dcSSimon Schubert Entering \"end\" on a line by itself is the normal way to terminate\n\
53685796c8dcSSimon Schubert such a list.\n\n\
53695796c8dcSSimon Schubert Note: the \"end\" command cannot be used at the gdb prompt."));
53705796c8dcSSimon Schubert 
53715796c8dcSSimon Schubert   add_com ("while-stepping", class_trace, while_stepping_pseudocommand, _("\
53725796c8dcSSimon Schubert Specify single-stepping behavior at a tracepoint.\n\
53735796c8dcSSimon Schubert Argument is number of instructions to trace in single-step mode\n\
53745796c8dcSSimon Schubert following the tracepoint.  This command is normally followed by\n\
53755796c8dcSSimon Schubert one or more \"collect\" commands, to specify what to collect\n\
53765796c8dcSSimon Schubert while single-stepping.\n\n\
53775796c8dcSSimon Schubert Note: this command can only be used in a tracepoint \"actions\" list."));
53785796c8dcSSimon Schubert 
53795796c8dcSSimon Schubert   add_com_alias ("ws", "while-stepping", class_alias, 0);
53805796c8dcSSimon Schubert   add_com_alias ("stepping", "while-stepping", class_alias, 0);
53815796c8dcSSimon Schubert 
53825796c8dcSSimon Schubert   add_com ("collect", class_trace, collect_pseudocommand, _("\
53835796c8dcSSimon Schubert Specify one or more data items to be collected at a tracepoint.\n\
53845796c8dcSSimon Schubert Accepts a comma-separated list of (one or more) expressions.  GDB will\n\
53855796c8dcSSimon Schubert collect all data (variables, registers) referenced by that expression.\n\
53865796c8dcSSimon Schubert Also accepts the following special arguments:\n\
53875796c8dcSSimon Schubert     $regs   -- all registers.\n\
53885796c8dcSSimon Schubert     $args   -- all function arguments.\n\
53895796c8dcSSimon Schubert     $locals -- all variables local to the block/function scope.\n\
5390cf7f2e2dSJohn Marino     $_sdata -- static tracepoint data (ignored for non-static tracepoints).\n\
5391cf7f2e2dSJohn Marino Note: this command can only be used in a tracepoint \"actions\" list."));
5392cf7f2e2dSJohn Marino 
5393cf7f2e2dSJohn Marino   add_com ("teval", class_trace, teval_pseudocommand, _("\
5394cf7f2e2dSJohn Marino Specify one or more expressions to be evaluated at a tracepoint.\n\
5395cf7f2e2dSJohn Marino Accepts a comma-separated list of (one or more) expressions.\n\
5396cf7f2e2dSJohn Marino The result of each evaluation will be discarded.\n\
53975796c8dcSSimon Schubert Note: this command can only be used in a tracepoint \"actions\" list."));
53985796c8dcSSimon Schubert 
53995796c8dcSSimon Schubert   add_com ("actions", class_trace, trace_actions_command, _("\
54005796c8dcSSimon Schubert Specify the actions to be taken at a tracepoint.\n\
54015796c8dcSSimon Schubert Tracepoint actions may include collecting of specified data,\n\
54025796c8dcSSimon Schubert single-stepping, or enabling/disabling other tracepoints,\n\
54035796c8dcSSimon Schubert depending on target's capabilities."));
54045796c8dcSSimon Schubert 
5405cf7f2e2dSJohn Marino   default_collect = xstrdup ("");
5406cf7f2e2dSJohn Marino   add_setshow_string_cmd ("default-collect", class_trace,
5407cf7f2e2dSJohn Marino 			  &default_collect, _("\
5408cf7f2e2dSJohn Marino Set the list of expressions to collect by default"), _("\
5409cf7f2e2dSJohn Marino Show the list of expressions to collect by default"), NULL,
5410cf7f2e2dSJohn Marino 			  NULL, NULL,
5411cf7f2e2dSJohn Marino 			  &setlist, &showlist);
5412cf7f2e2dSJohn Marino 
5413cf7f2e2dSJohn Marino   add_setshow_boolean_cmd ("disconnected-tracing", no_class,
5414cf7f2e2dSJohn Marino 			   &disconnected_tracing, _("\
5415cf7f2e2dSJohn Marino Set whether tracing continues after GDB disconnects."), _("\
5416cf7f2e2dSJohn Marino Show whether tracing continues after GDB disconnects."), _("\
5417cf7f2e2dSJohn Marino Use this to continue a tracing run even if GDB disconnects\n\
5418cf7f2e2dSJohn Marino or detaches from the target.  You can reconnect later and look at\n\
5419cf7f2e2dSJohn Marino trace data collected in the meantime."),
5420cf7f2e2dSJohn Marino 			   set_disconnected_tracing,
5421cf7f2e2dSJohn Marino 			   NULL,
5422cf7f2e2dSJohn Marino 			   &setlist,
5423cf7f2e2dSJohn Marino 			   &showlist);
5424cf7f2e2dSJohn Marino 
5425cf7f2e2dSJohn Marino   add_setshow_boolean_cmd ("circular-trace-buffer", no_class,
5426cf7f2e2dSJohn Marino 			   &circular_trace_buffer, _("\
5427cf7f2e2dSJohn Marino Set target's use of circular trace buffer."), _("\
5428cf7f2e2dSJohn Marino Show target's use of circular trace buffer."), _("\
5429cf7f2e2dSJohn Marino Use this to make the trace buffer into a circular buffer,\n\
5430cf7f2e2dSJohn Marino which will discard traceframes (oldest first) instead of filling\n\
5431cf7f2e2dSJohn Marino up and stopping the trace run."),
5432cf7f2e2dSJohn Marino 			   set_circular_trace_buffer,
5433cf7f2e2dSJohn Marino 			   NULL,
5434cf7f2e2dSJohn Marino 			   &setlist,
5435cf7f2e2dSJohn Marino 			   &showlist);
5436cf7f2e2dSJohn Marino 
5437*ef5ccd6cSJohn Marino   add_setshow_zuinteger_unlimited_cmd ("trace-buffer-size", no_class,
5438*ef5ccd6cSJohn Marino 				       &trace_buffer_size, _("\
5439*ef5ccd6cSJohn Marino Set requested size of trace buffer."), _("\
5440*ef5ccd6cSJohn Marino Show requested size of trace buffer."), _("\
5441*ef5ccd6cSJohn Marino Use this to choose a size for the trace buffer.  Some targets\n\
5442*ef5ccd6cSJohn Marino may have fixed or limited buffer sizes.  A value of -1 disables\n\
5443*ef5ccd6cSJohn Marino any attempt to set the buffer size and lets the target choose."),
5444*ef5ccd6cSJohn Marino 				       set_trace_buffer_size, NULL,
5445*ef5ccd6cSJohn Marino 				       &setlist, &showlist);
5446*ef5ccd6cSJohn Marino 
5447a45ae5f8SJohn Marino   add_setshow_string_cmd ("trace-user", class_trace,
5448a45ae5f8SJohn Marino 			  &trace_user, _("\
5449a45ae5f8SJohn Marino Set the user name to use for current and future trace runs"), _("\
5450a45ae5f8SJohn Marino Show the user name to use for current and future trace runs"), NULL,
5451a45ae5f8SJohn Marino 			  set_trace_user, NULL,
5452a45ae5f8SJohn Marino 			  &setlist, &showlist);
5453a45ae5f8SJohn Marino 
5454a45ae5f8SJohn Marino   add_setshow_string_cmd ("trace-notes", class_trace,
5455a45ae5f8SJohn Marino 			  &trace_notes, _("\
5456a45ae5f8SJohn Marino Set notes string to use for current and future trace runs"), _("\
5457a45ae5f8SJohn Marino Show the notes string to use for current and future trace runs"), NULL,
5458a45ae5f8SJohn Marino 			  set_trace_notes, NULL,
5459a45ae5f8SJohn Marino 			  &setlist, &showlist);
5460a45ae5f8SJohn Marino 
5461a45ae5f8SJohn Marino   add_setshow_string_cmd ("trace-stop-notes", class_trace,
5462a45ae5f8SJohn Marino 			  &trace_stop_notes, _("\
5463a45ae5f8SJohn Marino Set notes string to use for future tstop commands"), _("\
5464a45ae5f8SJohn Marino Show the notes string to use for future tstop commands"), NULL,
5465a45ae5f8SJohn Marino 			  set_trace_stop_notes, NULL,
5466a45ae5f8SJohn Marino 			  &setlist, &showlist);
5467a45ae5f8SJohn Marino 
5468cf7f2e2dSJohn Marino   init_tfile_ops ();
5469cf7f2e2dSJohn Marino 
5470cf7f2e2dSJohn Marino   add_target (&tfile_ops);
54715796c8dcSSimon Schubert }
5472