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 (¤t_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