]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tracepoint.c
Add sanitization for FR30
[thirdparty/binutils-gdb.git] / gdb / tracepoint.c
CommitLineData
6a02d201 1/* Tracing functionality for remote targets in custom GDB protocol
ad3b8c4a 2 Copyright 1997, 1998 Free Software Foundation, Inc.
6a02d201
MS
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "defs.h"
21#include "symtab.h"
22#include "frame.h"
23#include "tracepoint.h"
24#include "gdbtypes.h"
25#include "expression.h"
26#include "gdbcmd.h"
27#include "value.h"
28#include "target.h"
29#include "language.h"
6156728b 30#include "gdb_string.h"
6a02d201 31
9fe11cd1
MS
32#include "ax.h"
33#include "ax-gdb.h"
34
6a02d201
MS
35/* readline include files */
36#include "readline.h"
37#include "history.h"
38
39/* readline defines this. */
40#undef savestring
41
42#ifdef HAVE_UNISTD_H
43#include <unistd.h>
44#endif
45
9fe11cd1
MS
46/* maximum length of an agent aexpression.
47 this accounts for the fact that packets are limited to 400 bytes
48 (which includes everything -- including the checksum), and assumes
49 the worst case of maximum length for each of the pieces of a
50 continuation packet.
51
52 NOTE: expressions get mem2hex'ed otherwise this would be twice as
53 large. (400 - 31)/2 == 184 */
54#define MAX_AGENT_EXPR_LEN 184
55
56
6a02d201 57extern int info_verbose;
6c3908db
KS
58extern void (*readline_begin_hook) PARAMS ((char *, ...));
59extern char * (*readline_hook) PARAMS ((char *));
60extern void (*readline_end_hook) PARAMS ((void));
e59ddd6e 61extern void x_command PARAMS ((char *, int));
9fe11cd1 62extern int addressprint; /* Print machine addresses? */
6a02d201
MS
63
64/* If this definition isn't overridden by the header files, assume
65 that isatty and fileno exist on this system. */
66#ifndef ISATTY
67#define ISATTY(FP) (isatty (fileno (FP)))
68#endif
69
8b9c29f5
MS
70/*
71 Tracepoint.c:
72
73 This module defines the following debugger commands:
74 trace : set a tracepoint on a function, line, or address.
75 info trace : list all debugger-defined tracepoints.
76 delete trace : delete one or more tracepoints.
77 enable trace : enable one or more tracepoints.
78 disable trace : disable one or more tracepoints.
79 actions : specify actions to be taken at a tracepoint.
80 passcount : specify a pass count for a tracepoint.
81 tstart : start a trace experiment.
82 tstop : stop a trace experiment.
83 tstatus : query the status of a trace experiment.
84 tfind : find a trace frame in the trace buffer.
85 tdump : print everything collected at the current tracepoint.
86 save-tracepoints : write tracepoint setup into a file.
87
88 This module defines the following user-visible debugger variables:
89 $trace_frame : sequence number of trace frame currently being debugged.
90 $trace_line : source line of trace frame currently being debugged.
91 $trace_file : source file of trace frame currently being debugged.
92 $tracepoint : tracepoint number of trace frame currently being debugged.
93 */
94
95
96/* ======= Important global variables: ======= */
97
6a02d201
MS
98/* Chain of all tracepoints defined. */
99struct tracepoint *tracepoint_chain;
100
101/* Number of last tracepoint made. */
102static int tracepoint_count;
103
104/* Number of last traceframe collected. */
105static int traceframe_number;
106
6156728b
MS
107/* Tracepoint for last traceframe collected. */
108static int tracepoint_number;
109
110/* Symbol for function for last traceframe collected */
111static struct symbol *traceframe_fun;
112
113/* Symtab and line for last traceframe collected */
114static struct symtab_and_line traceframe_sal;
115
8b9c29f5
MS
116/* Tracing command lists */
117static struct cmd_list_element *tfindlist;
8b9c29f5
MS
118
119/* ======= Important command functions: ======= */
120static void trace_command PARAMS ((char *, int));
121static void tracepoints_info PARAMS ((char *, int));
122static void delete_trace_command PARAMS ((char *, int));
123static void enable_trace_command PARAMS ((char *, int));
124static void disable_trace_command PARAMS ((char *, int));
125static void trace_pass_command PARAMS ((char *, int));
126static void trace_actions_command PARAMS ((char *, int));
127static void trace_start_command PARAMS ((char *, int));
128static void trace_stop_command PARAMS ((char *, int));
129static void trace_status_command PARAMS ((char *, int));
130static void trace_find_command PARAMS ((char *, int));
131static void trace_find_pc_command PARAMS ((char *, int));
132static void trace_find_tracepoint_command PARAMS ((char *, int));
133static void trace_find_line_command PARAMS ((char *, int));
134static void trace_find_range_command PARAMS ((char *, int));
135static void trace_find_outside_command PARAMS ((char *, int));
136static void tracepoint_save_command PARAMS ((char *, int));
137static void trace_dump_command PARAMS ((char *, int));
138
9fe11cd1
MS
139/* support routines */
140static void trace_mention PARAMS ((struct tracepoint *));
141
142struct collection_list;
143static void add_aexpr PARAMS ((struct collection_list *, struct agent_expr *));
144static unsigned char *mem2hex(unsigned char *, unsigned char *, int);
8b9c29f5 145
6a02d201
MS
146/* Utility: returns true if "target remote" */
147static int
148target_is_remote ()
149{
150 if (current_target.to_shortname &&
151 strcmp (current_target.to_shortname, "remote") == 0)
152 return 1;
153 else
154 return 0;
155}
156
157/* Utility: generate error from an incoming stub packet. */
158static void
159trace_error (buf)
160 char *buf;
161{
162 if (*buf++ != 'E')
163 return; /* not an error msg */
164 switch (*buf)
165 {
166 case '1': /* malformed packet error */
167 if (*++buf == '0') /* general case: */
6156728b 168 error ("tracepoint.c: error in outgoing packet.");
6a02d201 169 else
6156728b
MS
170 error ("tracepoint.c: error in outgoing packet at field #%d.",
171 strtol (buf, NULL, 16));
6a02d201 172 case '2':
6156728b 173 error ("trace API error 0x%s.", ++buf);
6a02d201
MS
174 default:
175 error ("Target returns error code '%s'.", buf);
176 }
177}
178
6a02d201 179/* Utility: wait for reply from stub, while accepting "O" packets */
6156728b 180static char *
6a02d201
MS
181remote_get_noisy_reply (buf)
182 char *buf;
183{
184 do /* loop on reply from remote stub */
185 {
9fe11cd1 186 QUIT; /* allow user to bail out with ^C */
6a02d201
MS
187 getpkt (buf, 0);
188 if (buf[0] == 0)
189 error ("Target does not support this command.");
190 else if (buf[0] == 'E')
191 trace_error (buf);
6a02d201
MS
192 else if (buf[0] == 'O' &&
193 buf[1] != 'K')
194 remote_console_output (buf + 1); /* 'O' message from stub */
195 else
6156728b 196 return buf; /* here's the actual reply */
6a02d201
MS
197 } while (1);
198}
199
200/* Set tracepoint count to NUM. */
201static void
202set_tracepoint_count (num)
203 int num;
204{
205 tracepoint_count = num;
206 set_internalvar (lookup_internalvar ("tpnum"),
207 value_from_longest (builtin_type_int, (LONGEST) num));
208}
209
210/* Set traceframe number to NUM. */
211static void
212set_traceframe_num (num)
213 int num;
214{
215 traceframe_number = num;
216 set_internalvar (lookup_internalvar ("trace_frame"),
217 value_from_longest (builtin_type_int, (LONGEST) num));
218}
219
6156728b
MS
220/* Set tracepoint number to NUM. */
221static void
222set_tracepoint_num (num)
223 int num;
224{
225 tracepoint_number = num;
226 set_internalvar (lookup_internalvar ("tracepoint"),
227 value_from_longest (builtin_type_int, (LONGEST) num));
228}
229
230/* Set externally visible debug variables for querying/printing
231 the traceframe context (line, function, file) */
232
233static void
234set_traceframe_context (trace_pc)
235 CORE_ADDR trace_pc;
236{
237 static struct type *func_string, *file_string;
238 static struct type *func_range, *file_range;
239 static value_ptr func_val, file_val;
240 static struct type *charstar;
241 int len;
242
243 if (charstar == (struct type *) NULL)
244 charstar = lookup_pointer_type (builtin_type_char);
245
246 if (trace_pc == -1) /* cease debugging any trace buffers */
247 {
248 traceframe_fun = 0;
249 traceframe_sal.pc = traceframe_sal.line = 0;
250 traceframe_sal.symtab = NULL;
251 set_internalvar (lookup_internalvar ("trace_func"),
252 value_from_longest (charstar, (LONGEST) 0));
253 set_internalvar (lookup_internalvar ("trace_file"),
254 value_from_longest (charstar, (LONGEST) 0));
255 set_internalvar (lookup_internalvar ("trace_line"),
256 value_from_longest (builtin_type_int, (LONGEST) -1));
257 return;
258 }
259
260 /* save as globals for internal use */
261 traceframe_sal = find_pc_line (trace_pc, 0);
262 traceframe_fun = find_pc_function (trace_pc);
263
264 /* save linenumber as "$trace_line", a debugger variable visible to users */
265 set_internalvar (lookup_internalvar ("trace_line"),
266 value_from_longest (builtin_type_int,
267 (LONGEST) traceframe_sal.line));
268
269 /* save func name as "$trace_func", a debugger variable visible to users */
270 if (traceframe_fun == NULL ||
271 SYMBOL_NAME (traceframe_fun) == NULL)
272 set_internalvar (lookup_internalvar ("trace_func"),
273 value_from_longest (charstar, (LONGEST) 0));
274 else
275 {
276 len = strlen (SYMBOL_NAME (traceframe_fun));
277 func_range = create_range_type (func_range,
278 builtin_type_int, 0, len - 1);
279 func_string = create_array_type (func_string,
280 builtin_type_char, func_range);
281 func_val = allocate_value (func_string);
282 VALUE_TYPE (func_val) = func_string;
283 memcpy (VALUE_CONTENTS_RAW (func_val),
284 SYMBOL_NAME (traceframe_fun),
285 len);
286 func_val->modifiable = 0;
287 set_internalvar (lookup_internalvar ("trace_func"), func_val);
288 }
289
290 /* save file name as "$trace_file", a debugger variable visible to users */
291 if (traceframe_sal.symtab == NULL ||
292 traceframe_sal.symtab->filename == NULL)
293 set_internalvar (lookup_internalvar ("trace_file"),
294 value_from_longest (charstar, (LONGEST) 0));
295 else
296 {
297 len = strlen (traceframe_sal.symtab->filename);
298 file_range = create_range_type (file_range,
299 builtin_type_int, 0, len - 1);
300 file_string = create_array_type (file_string,
301 builtin_type_char, file_range);
302 file_val = allocate_value (file_string);
303 VALUE_TYPE (file_val) = file_string;
304 memcpy (VALUE_CONTENTS_RAW (file_val),
305 traceframe_sal.symtab->filename,
306 len);
307 file_val->modifiable = 0;
308 set_internalvar (lookup_internalvar ("trace_file"), file_val);
309 }
310}
311
6a02d201
MS
312/* Low level routine to set a tracepoint.
313 Returns the tracepoint object so caller can set other things.
314 Does not set the tracepoint number!
315 Does not print anything.
316
317 ==> This routine should not be called if there is a chance of later
318 error(); otherwise it leaves a bogus tracepoint on the chain. Validate
319 your arguments BEFORE calling this routine! */
320
321static struct tracepoint *
322set_raw_tracepoint (sal)
323 struct symtab_and_line sal;
324{
325 register struct tracepoint *t, *tc;
326 struct cleanup *old_chain;
327
328 t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
329 old_chain = make_cleanup (free, t);
330 memset (t, 0, sizeof (*t));
331 t->address = sal.pc;
332 if (sal.symtab == NULL)
333 t->source_file = NULL;
334 else
2e7eeba9
MS
335 t->source_file = savestring (sal.symtab->filename,
336 strlen (sal.symtab->filename));
57c0b026 337
2e7eeba9
MS
338 t->section = sal.section;
339 t->language = current_language->la_language;
6a02d201
MS
340 t->input_radix = input_radix;
341 t->line_number = sal.line;
7a880bf3
MS
342 t->enabled = enabled;
343 t->next = 0;
344 t->step_count = 0;
345 t->pass_count = 0;
346 t->addr_string = NULL;
6a02d201
MS
347
348 /* Add this tracepoint to the end of the chain
349 so that a list of tracepoints will come out in order
350 of increasing numbers. */
351
352 tc = tracepoint_chain;
353 if (tc == 0)
354 tracepoint_chain = t;
355 else
356 {
357 while (tc->next)
358 tc = tc->next;
359 tc->next = t;
360 }
361 discard_cleanups (old_chain);
362 return t;
363}
364
8b9c29f5 365/* Set a tracepoint according to ARG (function, linenum or *address) */
6a02d201
MS
366static void
367trace_command (arg, from_tty)
368 char *arg;
369 int from_tty;
370{
371 char **canonical = (char **)NULL;
372 struct symtabs_and_lines sals;
373 struct symtab_and_line sal;
374 struct tracepoint *t;
bf1aae13 375 char *addr_start = 0, *addr_end = 0;
6a02d201
MS
376 int i;
377
378 if (!arg || !*arg)
379 error ("trace command requires an argument");
380
381 if (from_tty && info_verbose)
382 printf_filtered ("TRACE %s\n", arg);
383
6a02d201
MS
384 addr_start = arg;
385 sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical);
386 addr_end = arg;
387 if (! sals.nelts)
388 return; /* ??? Presumably decode_line_1 has already warned? */
389
390 /* Resolve all line numbers to PC's */
391 for (i = 0; i < sals.nelts; i++)
392 resolve_sal_pc (&sals.sals[i]);
393
394 /* Now set all the tracepoints. */
395 for (i = 0; i < sals.nelts; i++)
396 {
397 sal = sals.sals[i];
398
399 t = set_raw_tracepoint (sal);
400 set_tracepoint_count (tracepoint_count + 1);
401 t->number = tracepoint_count;
402
403 /* If a canonical line spec is needed use that instead of the
6156728b 404 command string. */
6a02d201 405 if (canonical != (char **)NULL && canonical[i] != NULL)
6156728b 406 t->addr_string = canonical[i];
6a02d201 407 else if (addr_start)
6156728b 408 t->addr_string = savestring (addr_start, addr_end - addr_start);
57c0b026 409
9fe11cd1
MS
410 trace_mention (t);
411
57c0b026
MS
412 /* Let the UI know of any additions */
413 if (create_tracepoint_hook)
6156728b 414 create_tracepoint_hook (t);
6a02d201
MS
415 }
416
417 if (sals.nelts > 1)
418 {
419 printf_filtered ("Multiple tracepoints were set.\n");
8b9c29f5 420 printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
6a02d201
MS
421 }
422}
423
9fe11cd1
MS
424/* Tell the user we have just set a tracepoint TP. */
425
426static void
427trace_mention (tp)
428 struct tracepoint *tp;
429{
430 printf_filtered ("Tracepoint %d", tp->number);
431
432 if (addressprint || (tp->source_file == NULL))
433 {
434 printf_filtered (" at ");
435 print_address_numeric (tp->address, 1, gdb_stdout);
436 }
437 if (tp->source_file)
438 printf_filtered (": file %s, line %d.",
439 tp->source_file, tp->line_number);
440
441 printf_filtered ("\n");
442}
443
8b9c29f5
MS
444/* Print information on tracepoint number TPNUM_EXP, or all if omitted. */
445
6a02d201
MS
446static void
447tracepoints_info (tpnum_exp, from_tty)
448 char *tpnum_exp;
449 int from_tty;
450{
451 struct tracepoint *t;
452 struct action_line *action;
453 int found_a_tracepoint = 0;
454 char wrap_indent[80];
455 struct symbol *sym;
456 int tpnum = -1;
6a02d201
MS
457
458 if (tpnum_exp)
459 tpnum = parse_and_eval_address (tpnum_exp);
460
461 ALL_TRACEPOINTS (t)
462 if (tpnum == -1 || tpnum == t->number)
463 {
464 extern int addressprint; /* print machine addresses? */
465
466 if (!found_a_tracepoint++)
6156728b
MS
467 {
468 printf_filtered ("Num Enb ");
469 if (addressprint)
470 printf_filtered ("Address ");
471 printf_filtered ("PassC StepC What\n");
472 }
6a02d201
MS
473 strcpy (wrap_indent, " ");
474 if (addressprint)
475 strcat (wrap_indent, " ");
476
6156728b
MS
477 printf_filtered ("%-3d %-3s ", t->number,
478 t->enabled == enabled ? "y" : "n");
6a02d201 479 if (addressprint)
6156728b 480 printf_filtered ("%s ",
74c1b0ba 481 local_hex_string_custom ((unsigned long) t->address,
6156728b
MS
482 "08l"));
483 printf_filtered ("%-5d %-5d ", t->pass_count, t->step_count);
484
6a02d201
MS
485 if (t->source_file)
486 {
2e7eeba9 487 sym = find_pc_sect_function (t->address, t->section);
6a02d201
MS
488 if (sym)
489 {
490 fputs_filtered ("in ", gdb_stdout);
491 fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
492 wrap_here (wrap_indent);
493 fputs_filtered (" at ", gdb_stdout);
494 }
495 fputs_filtered (t->source_file, gdb_stdout);
496 printf_filtered (":%d", t->line_number);
497 }
498 else
499 print_address_symbolic (t->address, gdb_stdout, demangle, " ");
500
6a02d201
MS
501 printf_filtered ("\n");
502 if (t->actions)
503 {
504 printf_filtered (" Actions for tracepoint %d: \n", t->number);
6a02d201
MS
505 for (action = t->actions; action; action = action->next)
506 {
6a02d201 507 printf_filtered ("\t%s\n", action->action);
6a02d201
MS
508 }
509 }
510 }
511 if (!found_a_tracepoint)
512 {
513 if (tpnum == -1)
514 printf_filtered ("No tracepoints.\n");
515 else
516 printf_filtered ("No tracepoint number %d.\n", tpnum);
517 }
518}
519
520/* Optimization: the code to parse an enable, disable, or delete TP command
521 is virtually identical except for whether it performs an enable, disable,
522 or delete. Therefore I've combined them into one function with an opcode.
523 */
524enum tracepoint_opcode
525{
526 enable,
527 disable,
528 delete
529};
530
531/* This function implements enable, disable and delete. */
532static void
533tracepoint_operation (t, from_tty, opcode)
534 struct tracepoint *t;
535 int from_tty;
536 enum tracepoint_opcode opcode;
537{
538 struct tracepoint *t2;
6a02d201
MS
539
540 switch (opcode) {
541 case enable:
542 t->enabled = enabled;
a5f4fbff
KS
543 if (modify_tracepoint_hook)
544 modify_tracepoint_hook (t);
6a02d201
MS
545 break;
546 case disable:
547 t->enabled = disabled;
a5f4fbff
KS
548 if (modify_tracepoint_hook)
549 modify_tracepoint_hook (t);
6a02d201
MS
550 break;
551 case delete:
552 if (tracepoint_chain == t)
553 tracepoint_chain = t->next;
554
555 ALL_TRACEPOINTS (t2)
556 if (t2->next == t)
557 {
558 t2->next = t->next;
559 break;
560 }
57c0b026
MS
561
562 /* Let the UI know of any deletions */
563 if (delete_tracepoint_hook)
564 delete_tracepoint_hook (t);
565
6a02d201
MS
566 if (t->addr_string)
567 free (t->addr_string);
568 if (t->source_file)
569 free (t->source_file);
d9ba1c3f
MS
570 if (t->actions)
571 free_actions (t);
572
6a02d201
MS
573 free (t);
574 break;
575 }
576}
577
578/* Utility: parse a tracepoint number and look it up in the list. */
57c0b026 579struct tracepoint *
6a02d201
MS
580get_tracepoint_by_number (arg)
581 char **arg;
582{
583 struct tracepoint *t;
6156728b 584 char *end, *copy;
6a02d201
MS
585 value_ptr val;
586 int tpnum;
587
588 if (arg == 0)
589 error ("Bad tracepoint argument");
590
591 if (*arg == 0 || **arg == 0) /* empty arg means refer to last tp */
592 tpnum = tracepoint_count;
593 else if (**arg == '$') /* handle convenience variable */
594 {
6156728b
MS
595 /* Make a copy of the name, so we can null-terminate it
596 to pass to lookup_internalvar(). */
597 end = *arg + 1;
598 while (isalnum(*end) || *end == '_')
599 end++;
600 copy = (char *) alloca (end - *arg);
601 strncpy (copy, *arg + 1, (end - *arg - 1));
602 copy[end - *arg - 1] = '\0';
603 *arg = end;
604
605 val = value_of_internalvar (lookup_internalvar (copy));
6a02d201
MS
606 if (TYPE_CODE( VALUE_TYPE (val)) != TYPE_CODE_INT)
607 error ("Convenience variable must have integral type.");
608 tpnum = (int) value_as_long (val);
609 }
610 else /* handle tracepoint number */
611 {
9fe11cd1
MS
612 tpnum = strtol (*arg, arg, 0);
613 if (tpnum == 0) /* possible strtol failure */
614 while (**arg && !isspace (**arg))
615 (*arg)++; /* advance to next white space, if any */
6a02d201
MS
616 }
617 ALL_TRACEPOINTS (t)
618 if (t->number == tpnum)
619 {
620 return t;
621 }
9fe11cd1 622 printf_unfiltered ("No tracepoint number %d.\n", tpnum);
6a02d201
MS
623 return NULL;
624}
625
626/* Utility: parse a list of tracepoint numbers, and call a func for each. */
627static void
628map_args_over_tracepoints (args, from_tty, opcode)
629 char *args;
630 int from_tty;
631 enum tracepoint_opcode opcode;
632{
99fa2de0 633 struct tracepoint *t, *tmp;
6a02d201
MS
634 int tpnum;
635 char *cp;
636
637 if (args == 0 || *args == 0) /* do them all */
99fa2de0 638 ALL_TRACEPOINTS_SAFE (t, tmp)
6a02d201
MS
639 tracepoint_operation (t, from_tty, opcode);
640 else
641 while (*args)
642 {
9fe11cd1 643 QUIT; /* give user option to bail out with ^C */
6a02d201
MS
644 if (t = get_tracepoint_by_number (&args))
645 tracepoint_operation (t, from_tty, opcode);
646 while (*args == ' ' || *args == '\t')
647 args++;
648 }
649}
650
8b9c29f5 651/* The 'enable trace' command enables tracepoints. Not supported by all targets. */
6a02d201
MS
652static void
653enable_trace_command (args, from_tty)
654 char *args;
655 int from_tty;
656{
657 dont_repeat ();
658 map_args_over_tracepoints (args, from_tty, enable);
659}
660
8b9c29f5 661/* The 'disable trace' command enables tracepoints. Not supported by all targets. */
6a02d201
MS
662static void
663disable_trace_command (args, from_tty)
664 char *args;
665 int from_tty;
666{
667 dont_repeat ();
668 map_args_over_tracepoints (args, from_tty, disable);
669}
670
8b9c29f5 671/* Remove a tracepoint (or all if no argument) */
6a02d201
MS
672static void
673delete_trace_command (args, from_tty)
674 char *args;
675 int from_tty;
676{
677 dont_repeat ();
9fe11cd1
MS
678 if (!args || !*args) /* No args implies all tracepoints; */
679 if (from_tty) /* confirm only if from_tty... */
680 if (tracepoint_chain) /* and if there are tracepoints to delete! */
681 if (!query ("Delete all tracepoints? "))
682 return;
6a02d201
MS
683
684 map_args_over_tracepoints (args, from_tty, delete);
685}
686
8b9c29f5
MS
687/* Set passcount for tracepoint.
688
689 First command argument is passcount, second is tracepoint number.
690 If tracepoint number omitted, apply to most recently defined.
691 Also accepts special argument "all". */
692
6a02d201
MS
693static void
694trace_pass_command (args, from_tty)
695 char *args;
696 int from_tty;
697{
698 struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
699 unsigned long count;
700
701 if (args == 0 || *args == 0)
702 error ("PASS command requires an argument (count + optional TP num)");
703
704 count = strtoul (args, &args, 10); /* count comes first, then TP num */
705
706 while (*args && isspace (*args))
707 args++;
708
709 if (*args && strncasecmp (args, "all", 3) == 0)
710 args += 3; /* skip special argument "all" */
711 else
712 t1 = get_tracepoint_by_number (&args);
713
9fe11cd1
MS
714 if (*args)
715 error ("Junk at end of arguments.");
716
6a02d201
MS
717 if (t1 == NULL)
718 return; /* error, bad tracepoint number */
719
720 ALL_TRACEPOINTS (t2)
721 if (t1 == (struct tracepoint *) -1 || t1 == t2)
722 {
723 t2->pass_count = count;
41158958
EZ
724 if (modify_tracepoint_hook)
725 modify_tracepoint_hook (t2);
6a02d201
MS
726 if (from_tty)
727 printf_filtered ("Setting tracepoint %d's passcount to %d\n",
728 t2->number, count);
729 }
730}
731
8b9c29f5
MS
732/* ACTIONS functions: */
733
734/* Prototypes for action-parsing utility commands */
735static void read_actions PARAMS((struct tracepoint *));
8b9c29f5
MS
736static char *parse_and_eval_memrange PARAMS ((char *,
737 CORE_ADDR,
738 long *,
739 bfd_signed_vma *,
740 long *));
741
742/* The three functions:
728c7f37
MS
743 collect_pseudocommand,
744 while_stepping_pseudocommand, and
745 end_actions_pseudocommand
8b9c29f5
MS
746 are placeholders for "commands" that are actually ONLY to be used
747 within a tracepoint action list. If the actual function is ever called,
748 it means that somebody issued the "command" at the top level,
749 which is always an error. */
6a02d201 750
6156728b 751static void
728c7f37 752end_actions_pseudocommand (args, from_tty)
5d187fd3
MS
753 char *args;
754 int from_tty;
6156728b
MS
755{
756 error ("This command cannot be used at the top level.");
757}
758
759static void
728c7f37 760while_stepping_pseudocommand (args, from_tty)
5d187fd3
MS
761 char *args;
762 int from_tty;
6156728b
MS
763{
764 error ("This command can only be used in a tracepoint actions list.");
765}
766
767static void
728c7f37 768collect_pseudocommand (args, from_tty)
5d187fd3
MS
769 char *args;
770 int from_tty;
6156728b
MS
771{
772 error ("This command can only be used in a tracepoint actions list.");
773}
774
8b9c29f5 775/* Enter a list of actions for a tracepoint. */
6a02d201
MS
776static void
777trace_actions_command (args, from_tty)
778 char *args;
779 int from_tty;
780{
781 struct tracepoint *t;
782 char *actions;
6c3908db
KS
783 char tmpbuf[128];
784 char *end_msg = "End with a line saying just \"end\".";
6a02d201
MS
785
786 if (t = get_tracepoint_by_number (&args))
787 {
6c3908db
KS
788 sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
789 t->number);
790
7a880bf3
MS
791 if (from_tty)
792 {
793 if (readline_begin_hook)
794 (*readline_begin_hook) ("%s %s\n", tmpbuf, end_msg);
795 else if (input_from_terminal_p ())
796 printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
797 }
6c3908db 798
6a02d201 799 free_actions (t);
9fe11cd1 800 t->step_count = 0; /* read_actions may set this */
6a02d201 801 read_actions (t);
6c3908db
KS
802
803 if (readline_end_hook)
804 (*readline_end_hook) ();
805
6a02d201
MS
806 /* tracepoints_changed () */
807 }
808 /* else error, just return; */
809}
810
8b9c29f5 811/* worker function */
6a02d201
MS
812static void
813read_actions (t)
814 struct tracepoint *t;
815{
816 char *line;
817 char *prompt1 = "> ", *prompt2 = " > ";
818 char *prompt = prompt1;
819 enum actionline_type linetype;
820 extern FILE *instream;
821 struct action_line *next = NULL, *temp;
822 struct cleanup *old_chain;
823
824 /* Control-C quits instantly if typed while in this loop
825 since it should not wait until the user types a newline. */
826 immediate_quit++;
827#ifdef STOP_SIGNAL
828 if (job_control)
829 signal (STOP_SIGNAL, stop_sig);
830#endif
ad3b8c4a 831 old_chain = make_cleanup ((make_cleanup_func) free_actions, (void *) t);
6a02d201
MS
832 while (1)
833 {
834 /* Make sure that all output has been output. Some machines may let
835 you get away with leaving out some of the gdb_flush, but not all. */
836 wrap_here ("");
837 gdb_flush (gdb_stdout);
838 gdb_flush (gdb_stderr);
6c3908db
KS
839
840 if (readline_hook && instream == NULL)
841 line = (*readline_hook) (prompt);
842 else if (instream == stdin && ISATTY (instream))
99fa2de0
MS
843 {
844 line = readline (prompt);
845 if (line && *line) /* add it to command history */
846 add_history (line);
847 }
6a02d201
MS
848 else
849 line = gdb_readline (0);
850
d9ba1c3f 851 linetype = validate_actionline (&line, t);
6a02d201
MS
852 if (linetype == BADLINE)
853 continue; /* already warned -- collect another line */
854
9fe11cd1 855 temp = xmalloc (sizeof (struct action_line));
6a02d201
MS
856 temp->next = NULL;
857 temp->action = line;
858
859 if (next == NULL) /* first action for this tracepoint? */
860 t->actions = next = temp;
861 else
862 {
863 next->next = temp;
864 next = temp;
865 }
866
867 if (linetype == STEPPING) /* begin "while-stepping" */
868 if (prompt == prompt2)
869 {
870 warning ("Already processing 'while-stepping'");
871 continue;
872 }
873 else
874 prompt = prompt2; /* change prompt for stepping actions */
875 else if (linetype == END)
876 if (prompt == prompt2)
9fe11cd1
MS
877 {
878 prompt = prompt1; /* end of single-stepping actions */
879 }
6a02d201 880 else
9fe11cd1
MS
881 { /* end of actions */
882 if (t->actions->next == NULL)
883 {
884 /* an "end" all by itself with no other actions means
885 this tracepoint has no actions. Discard empty list. */
886 free_actions (t);
887 }
888 break;
889 }
6a02d201
MS
890 }
891#ifdef STOP_SIGNAL
892 if (job_control)
893 signal (STOP_SIGNAL, SIG_DFL);
894#endif
895 immediate_quit = 0;
896 discard_cleanups (old_chain);
897}
898
8b9c29f5 899/* worker function */
9fe11cd1 900enum actionline_type
6a02d201 901validate_actionline (line, t)
d9ba1c3f 902 char **line;
6a02d201
MS
903 struct tracepoint *t;
904{
728c7f37 905 struct cmd_list_element *c;
9fe11cd1 906 struct expression *exp = NULL;
6a02d201 907 value_ptr temp, temp2;
9fe11cd1 908 struct cleanup *old_chain = NULL;
728c7f37 909 char *p;
6a02d201 910
d9ba1c3f 911 for (p = *line; isspace (*p); )
6a02d201
MS
912 p++;
913
914 /* symbol lookup etc. */
915 if (*p == '\0') /* empty line: just prompt for another line. */
916 return BADLINE;
728c7f37 917
5d187fd3
MS
918 if (*p == '#') /* comment line */
919 return GENERIC;
920
728c7f37
MS
921 c = lookup_cmd (&p, cmdlist, "", -1, 1);
922 if (c == 0)
923 {
924 warning ("'%s' is not an action that I know, or is ambiguous.", p);
925 return BADLINE;
926 }
927
928 if (c->function.cfunc == collect_pseudocommand)
6a02d201 929 {
9fe11cd1
MS
930 struct agent_expr *aexpr;
931 struct agent_reqs areqs;
932
6a02d201 933 do { /* repeat over a comma-separated list */
9fe11cd1 934 QUIT; /* allow user to bail out with ^C */
6a02d201
MS
935 while (isspace (*p))
936 p++;
937
6156728b
MS
938 if (*p == '$') /* look for special pseudo-symbols */
939 {
940 long typecode, size;
941 bfd_signed_vma offset;
942
943 if ((0 == strncasecmp ("reg", p + 1, 3)) ||
944 (0 == strncasecmp ("arg", p + 1, 3)) ||
945 (0 == strncasecmp ("loc", p + 1, 3)))
d9ba1c3f 946 {
9fe11cd1
MS
947 p = strchr (p, ',');
948 continue;
d9ba1c3f 949 }
9fe11cd1 950 /* else fall thru, treat p as an expression and parse it! */
6156728b 951 }
9fe11cd1 952 exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
ad3b8c4a
JM
953 old_chain = make_cleanup ((make_cleanup_func) free_current_contents,
954 &exp);
6156728b 955
9fe11cd1
MS
956 if (exp->elts[0].opcode == OP_VAR_VALUE)
957 if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
958 {
959 warning ("%s is constant (value %d): will not be collected.",
960 SYMBOL_NAME (exp->elts[2].symbol),
961 SYMBOL_VALUE (exp->elts[2].symbol));
962 return BADLINE;
963 }
964 else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
965 {
966 warning ("%s is optimized away and cannot be collected.",
967 SYMBOL_NAME (exp->elts[2].symbol));
968 return BADLINE;
969 }
970
971 /* we have something to collect, make sure that the expr to
972 bytecode translator can handle it and that it's not too long */
973 aexpr = gen_trace_for_expr(exp);
ad3b8c4a 974 (void) make_cleanup ((make_cleanup_func) free_agent_expr, aexpr);
9fe11cd1
MS
975
976 if (aexpr->len > MAX_AGENT_EXPR_LEN)
977 error ("expression too complicated, try simplifying");
978
979 ax_reqs(aexpr, &areqs);
980 (void) make_cleanup (free, areqs.reg_mask);
981
982 if (areqs.flaw != agent_flaw_none)
983 error ("malformed expression");
984
985 if (areqs.min_height < 0)
986 error ("gdb: Internal error: expression has min height < 0");
987
988 if (areqs.max_height > 20)
989 error ("expression too complicated, try simplifying");
990
991 do_cleanups (old_chain);
6a02d201
MS
992 } while (p && *p++ == ',');
993 return GENERIC;
994 }
728c7f37 995 else if (c->function.cfunc == while_stepping_pseudocommand)
6a02d201
MS
996 {
997 char *steparg; /* in case warning is necessary */
998
6a02d201
MS
999 while (isspace (*p))
1000 p++;
1001 steparg = p;
1002
9fe11cd1
MS
1003 if (*p == '\0' ||
1004 (t->step_count = strtol (p, &p, 0)) == 0)
6a02d201 1005 {
9fe11cd1
MS
1006 warning ("bad step-count: command ignored.", *line);
1007 return BADLINE;
6a02d201 1008 }
6a02d201
MS
1009 return STEPPING;
1010 }
728c7f37 1011 else if (c->function.cfunc == end_actions_pseudocommand)
6a02d201
MS
1012 return END;
1013 else
1014 {
d9ba1c3f 1015 warning ("'%s' is not a supported tracepoint action.", *line);
6a02d201
MS
1016 return BADLINE;
1017 }
1018}
1019
8b9c29f5 1020/* worker function */
a5f4fbff 1021void
6a02d201
MS
1022free_actions (t)
1023 struct tracepoint *t;
1024{
1025 struct action_line *line, *next;
1026
1027 for (line = t->actions; line; line = next)
1028 {
1029 next = line->next;
d9ba1c3f
MS
1030 if (line->action)
1031 free (line->action);
6a02d201
MS
1032 free (line);
1033 }
1034 t->actions = NULL;
1035}
1036
1037struct memrange {
1038 int type; /* 0 for absolute memory range, else basereg number */
1039 bfd_signed_vma start;
1040 bfd_signed_vma end;
1041};
1042
1043struct collection_list {
1044 unsigned char regs_mask[8]; /* room for up to 256 regs */
1045 long listsize;
1046 long next_memrange;
1047 struct memrange *list;
9fe11cd1
MS
1048 long aexpr_listsize; /* size of array pointed to by expr_list elt */
1049 long next_aexpr_elt;
1050 struct agent_expr **aexpr_list;
1051
6a02d201
MS
1052} tracepoint_list, stepping_list;
1053
8b9c29f5
MS
1054/* MEMRANGE functions: */
1055
9fe11cd1 1056static int memrange_cmp PARAMS ((const void *, const void *));
8b9c29f5
MS
1057
1058/* compare memranges for qsort */
6a02d201 1059static int
9fe11cd1
MS
1060memrange_cmp (va, vb)
1061 const void *va;
1062 const void *vb;
6a02d201 1063{
9fe11cd1 1064 const struct memrange *a = va, *b = vb;
59813131 1065
9fe11cd1
MS
1066 if (a->type < b->type)
1067 return -1;
1068 if (a->type > b->type)
1069 return 1;
6a02d201
MS
1070 if (a->type == 0)
1071 {
1072 if ((bfd_vma) a->start < (bfd_vma) b->start) return -1;
1073 if ((bfd_vma) a->start > (bfd_vma) b->start) return 1;
1074 }
1075 else
1076 {
9fe11cd1
MS
1077 if (a->start < b->start)
1078 return -1;
1079 if (a->start > b->start)
1080 return 1;
6a02d201
MS
1081 }
1082 return 0;
1083}
1084
8b9c29f5 1085/* Sort the memrange list using qsort, and merge adjacent memranges */
6a02d201
MS
1086static void
1087memrange_sortmerge (memranges)
1088 struct collection_list *memranges;
1089{
1090 int a, b;
1091
1092 qsort (memranges->list, memranges->next_memrange,
1093 sizeof (struct memrange), memrange_cmp);
1094 if (memranges->next_memrange > 0)
1095 {
1096 for (a = 0, b = 1; b < memranges->next_memrange; b++)
1097 {
1098 if (memranges->list[a].type == memranges->list[b].type &&
1099 memranges->list[b].start - memranges->list[a].end <=
1100 MAX_REGISTER_VIRTUAL_SIZE)
1101 {
5d187fd3
MS
1102 /* memrange b starts before memrange a ends; merge them. */
1103 if (memranges->list[b].end > memranges->list[a].end)
1104 memranges->list[a].end = memranges->list[b].end;
6a02d201
MS
1105 continue; /* next b, same a */
1106 }
1107 a++; /* next a */
1108 if (a != b)
1109 memcpy (&memranges->list[a], &memranges->list[b],
1110 sizeof (struct memrange));
1111 }
1112 memranges->next_memrange = a + 1;
1113 }
1114}
1115
8b9c29f5 1116/* Add a register to a collection list */
6a02d201
MS
1117void
1118add_register (collection, regno)
1119 struct collection_list *collection;
1120 unsigned long regno;
1121{
1122 if (info_verbose)
1123 printf_filtered ("collect register %d\n", regno);
1124 if (regno > (8 * sizeof (collection->regs_mask)))
1125 error ("Internal: register number %d too large for tracepoint",
1126 regno);
1127 collection->regs_mask [regno / 8] |= 1 << (regno % 8);
1128}
1129
8b9c29f5 1130/* Add a memrange to a collection list */
6a02d201
MS
1131static void
1132add_memrange (memranges, type, base, len)
1133 struct collection_list *memranges;
1134 int type;
1135 bfd_signed_vma base;
1136 unsigned long len;
1137{
1138 if (info_verbose)
1139 printf_filtered ("(%d,0x%x,%d)\n", type, base, len);
1140 /* type: 0 == memory, n == basereg */
1141 memranges->list[memranges->next_memrange].type = type;
1142 /* base: addr if memory, offset if reg relative. */
1143 memranges->list[memranges->next_memrange].start = base;
1144 /* len: we actually save end (base + len) for convenience */
1145 memranges->list[memranges->next_memrange].end = base + len;
1146 memranges->next_memrange++;
1147 if (memranges->next_memrange >= memranges->listsize)
1148 {
1149 memranges->listsize *= 2;
9fe11cd1 1150 memranges->list = xrealloc (memranges->list,
6a02d201
MS
1151 memranges->listsize);
1152 }
1153
d9ba1c3f 1154 if (type != -1) /* better collect the base register! */
6a02d201
MS
1155 add_register (memranges, type);
1156}
1157
8b9c29f5 1158/* Add a symbol to a collection list */
6a02d201
MS
1159static void
1160collect_symbol (collect, sym)
1161 struct collection_list *collect;
1162 struct symbol *sym;
1163{
1164 unsigned long len;
1165 unsigned long reg;
1166 bfd_signed_vma offset;
1167
1168 len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
1169 switch (SYMBOL_CLASS (sym)) {
1170 default:
1171 printf_filtered ("%s: don't know symbol class %d\n",
1172 SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
1173 break;
1174 case LOC_CONST:
1175 printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1176 SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
1177 break;
1178 case LOC_STATIC:
1179 offset = SYMBOL_VALUE_ADDRESS (sym);
1180 if (info_verbose)
60c7c376 1181 printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
6a02d201 1182 SYMBOL_NAME (sym), len, offset);
d9ba1c3f 1183 add_memrange (collect, -1, offset, len); /* 0 == memory */
6a02d201
MS
1184 break;
1185 case LOC_REGISTER:
1186 case LOC_REGPARM:
1187 reg = SYMBOL_VALUE (sym);
1188 if (info_verbose)
1189 printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
1190 add_register (collect, reg);
98760699
MS
1191 /* check for doubles stored in two registers */
1192 /* FIXME: how about larger types stored in 3 or more regs? */
1193 if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
1194 len > REGISTER_RAW_SIZE (reg))
1195 add_register (collect, reg + 1);
6a02d201 1196 break;
6a02d201 1197 case LOC_REF_ARG:
f32fa053 1198 printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
6a02d201
MS
1199 printf_filtered (" (will not collect %s)\n",
1200 SYMBOL_NAME (sym));
1201 break;
f32fa053
MS
1202 case LOC_ARG:
1203 offset = SYMBOL_VALUE (sym);
1204 reg = FP_REGNUM;
1205 if (info_verbose)
1206 {
1207 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1208 SYMBOL_NAME (sym), len);
1209 printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
1210 }
1211 add_memrange (collect, reg, offset, len);
1212 break;
6a02d201
MS
1213 case LOC_REGPARM_ADDR:
1214 reg = SYMBOL_VALUE (sym);
1215 offset = 0;
1216 if (info_verbose)
1217 {
f32fa053
MS
1218 printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset",
1219 SYMBOL_NAME (sym), len);
1220 printf_filtered (" %d from reg %d\n", offset, reg);
6a02d201
MS
1221 }
1222 add_memrange (collect, reg, offset, len);
1223 break;
1224 case LOC_LOCAL:
1225 case LOC_LOCAL_ARG:
1226 offset = SYMBOL_VALUE (sym);
1227 reg = FP_REGNUM;
1228 if (info_verbose)
1229 {
f32fa053
MS
1230 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1231 SYMBOL_NAME (sym), len);
1232 printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
6a02d201
MS
1233 }
1234 add_memrange (collect, reg, offset, len);
1235 break;
1236 case LOC_BASEREG:
1237 case LOC_BASEREG_ARG:
1238 reg = SYMBOL_BASEREG (sym);
1239 offset = SYMBOL_VALUE (sym);
1240 if (info_verbose)
1241 {
1242 printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n",
1243 SYMBOL_NAME (sym), len, offset, reg);
1244 }
1245 add_memrange (collect, reg, offset, len);
1246 break;
1247 case LOC_UNRESOLVED:
1248 printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
1249 break;
1250 case LOC_OPTIMIZED_OUT:
1251 printf_filtered ("%s has been optimized out of existance.\n",
1252 SYMBOL_NAME (sym));
1253 break;
1254 }
1255}
1256
8b9c29f5 1257/* Add all locals (or args) symbols to collection list */
6a02d201
MS
1258static void
1259add_local_symbols (collect, pc, type)
1260 struct collection_list *collect;
1261 CORE_ADDR pc;
9fe11cd1 1262 int type;
6a02d201
MS
1263{
1264 struct symbol *sym;
1265 struct block *block;
1266 int i, nsyms, count = 0;
1267
1268 block = block_for_pc (pc);
1269 while (block != 0)
1270 {
9fe11cd1 1271 QUIT; /* allow user to bail out with ^C */
6a02d201
MS
1272 nsyms = BLOCK_NSYMS (block);
1273 for (i = 0; i < nsyms; i++)
1274 {
1275 sym = BLOCK_SYM (block, i);
1276 switch (SYMBOL_CLASS (sym)) {
1277 case LOC_LOCAL:
1278 case LOC_STATIC:
1279 case LOC_REGISTER:
1280 case LOC_BASEREG:
1281 if (type == 'L') /* collecting Locals */
1282 {
1283 count++;
1284 collect_symbol (collect, sym);
1285 }
1286 break;
1287 case LOC_ARG:
1288 case LOC_LOCAL_ARG:
1289 case LOC_REF_ARG:
1290 case LOC_REGPARM:
1291 case LOC_REGPARM_ADDR:
1292 case LOC_BASEREG_ARG:
1293 if (type == 'A') /* collecting Arguments */
1294 {
1295 count++;
1296 collect_symbol (collect, sym);
1297 }
1298 }
1299 }
1300 if (BLOCK_FUNCTION (block))
1301 break;
1302 else
1303 block = BLOCK_SUPERBLOCK (block);
1304 }
1305 if (count == 0)
1306 warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
1307}
1308
8b9c29f5 1309/* worker function */
6a02d201
MS
1310static void
1311clear_collection_list (list)
1312 struct collection_list *list;
1313{
9fe11cd1
MS
1314 int ndx;
1315
6a02d201 1316 list->next_memrange = 0;
9fe11cd1
MS
1317 for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
1318 {
1319 free_agent_expr(list->aexpr_list[ndx]);
1320 list->aexpr_list[ndx] = NULL;
1321 }
1322 list->next_aexpr_elt = 0;
6a02d201
MS
1323 memset (list->regs_mask, 0, sizeof (list->regs_mask));
1324}
1325
8b9c29f5 1326/* reduce a collection list to string form (for gdb protocol) */
9fe11cd1 1327static char **
6a02d201
MS
1328stringify_collection_list (list, string)
1329 struct collection_list *list;
1330 char *string;
1331{
9fe11cd1
MS
1332 char temp_buf[2048];
1333 int count;
1334 int ndx = 0;
1335 char *(*str_list)[];
1336 char *end;
6a02d201
MS
1337 long i;
1338
9fe11cd1
MS
1339 count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
1340 str_list = (char *(*)[])xmalloc(count * sizeof (char *));
1341
6a02d201
MS
1342 for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1343 if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
1344 break;
1345 if (list->regs_mask[i] != 0) /* prepare to send regs_mask to the stub */
1346 {
1347 if (info_verbose)
1348 printf_filtered ("\nCollecting registers (mask): 0x");
9fe11cd1 1349 end = temp_buf;
6a02d201
MS
1350 *end++='R';
1351 for (; i >= 0; i--)
1352 {
9fe11cd1 1353 QUIT; /* allow user to bail out with ^C */
6a02d201
MS
1354 if (info_verbose)
1355 printf_filtered ("%02X", list->regs_mask[i]);
1356 sprintf (end, "%02X", list->regs_mask[i]);
1357 end += 2;
1358 }
9fe11cd1
MS
1359 (*str_list)[ndx] = savestring(temp_buf, end - temp_buf);
1360 ndx++;
6a02d201
MS
1361 }
1362 if (info_verbose)
1363 printf_filtered ("\n");
1364 if (list->next_memrange > 0 && info_verbose)
1365 printf_filtered ("Collecting memranges: \n");
9fe11cd1 1366 for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
6a02d201 1367 {
9fe11cd1 1368 QUIT; /* allow user to bail out with ^C */
6a02d201
MS
1369 if (info_verbose)
1370 printf_filtered ("(%d, 0x%x, %d)\n",
1371 list->list[i].type,
1372 list->list[i].start,
1373 list->list[i].end - list->list[i].start);
9fe11cd1
MS
1374 if (count + 27 > MAX_AGENT_EXPR_LEN)
1375 {
1376 (*str_list)[ndx] = savestring(temp_buf, count);
1377 ndx++;
1378 count = 0;
1379 end = temp_buf;
1380 }
6a02d201
MS
1381 sprintf (end, "M%X,%X,%X",
1382 list->list[i].type,
1383 list->list[i].start,
1384 list->list[i].end - list->list[i].start);
9fe11cd1 1385 count += strlen (end);
6a02d201
MS
1386 end += strlen (end);
1387 }
9fe11cd1
MS
1388
1389 for (i = 0; i < list->next_aexpr_elt; i++)
1390 {
1391 QUIT; /* allow user to bail out with ^C */
1392 if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
1393 {
1394 (*str_list)[ndx] = savestring(temp_buf, count);
1395 ndx++;
1396 count = 0;
1397 end = temp_buf;
1398 }
1399 sprintf (end, "X%08X,", list->aexpr_list[i]->len);
1400 end += 10; /* 'X' + 8 hex digits + ',' */
1401 count += 10;
1402
1403 end = mem2hex(list->aexpr_list[i]->buf, end, list->aexpr_list[i]->len);
1404 count += 2 * list->aexpr_list[i]->len;
1405 }
1406
1407 if (count != 0)
1408 {
1409 (*str_list)[ndx] = savestring(temp_buf, count);
1410 ndx++;
1411 count = 0;
1412 end = temp_buf;
1413 }
1414 (*str_list)[ndx] = NULL;
1415
1416 if (ndx == 0)
6a02d201
MS
1417 return NULL;
1418 else
9fe11cd1
MS
1419 return *str_list;
1420}
1421
1422void
1423free_actions_list(actions_list)
1424 char **actions_list;
1425{
1426 int ndx;
1427
1428 if (actions_list == 0)
1429 return;
1430
1431 for (ndx = 0; actions_list[ndx]; ndx++)
1432 free(actions_list[ndx]);
1433
1434 free(actions_list);
6a02d201
MS
1435}
1436
8b9c29f5 1437/* render all actions into gdb protocol */
6a02d201 1438static void
9fe11cd1 1439encode_actions (t, tdp_actions, stepping_actions)
6a02d201 1440 struct tracepoint *t;
9fe11cd1
MS
1441 char ***tdp_actions;
1442 char ***stepping_actions;
6a02d201 1443{
6a02d201 1444 static char tdp_buff[2048], step_buff[2048];
6a02d201 1445 char *action_exp;
9fe11cd1 1446 struct expression *exp = NULL;
728c7f37 1447 struct action_line *action;
6a02d201
MS
1448 bfd_signed_vma offset;
1449 long i;
d9ba1c3f 1450 value_ptr tempval;
728c7f37
MS
1451 struct collection_list *collect;
1452 struct cmd_list_element *cmd;
9fe11cd1 1453 struct agent_expr *aexpr;
6a02d201
MS
1454
1455 clear_collection_list (&tracepoint_list);
1456 clear_collection_list (&stepping_list);
1457 collect = &tracepoint_list;
1458
1459 *tdp_actions = NULL;
1460 *stepping_actions = NULL;
1461
1462 for (action = t->actions; action; action = action->next)
1463 {
9fe11cd1 1464 QUIT; /* allow user to bail out with ^C */
6a02d201
MS
1465 action_exp = action->action;
1466 while (isspace (*action_exp))
1467 action_exp++;
1468
5d187fd3
MS
1469 if (*action_exp == '#') /* comment line */
1470 return;
1471
728c7f37
MS
1472 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
1473 if (cmd == 0)
1474 error ("Bad action list item: %s", action_exp);
1475
1476 if (cmd->function.cfunc == collect_pseudocommand)
6a02d201 1477 {
6a02d201 1478 do { /* repeat over a comma-separated list */
9fe11cd1 1479 QUIT; /* allow user to bail out with ^C */
6a02d201
MS
1480 while (isspace (*action_exp))
1481 action_exp++;
1482
1483 if (0 == strncasecmp ("$reg", action_exp, 4))
1484 {
1485 for (i = 0; i < NUM_REGS; i++)
1486 add_register (collect, i);
6156728b 1487 action_exp = strchr (action_exp, ','); /* more? */
6a02d201
MS
1488 }
1489 else if (0 == strncasecmp ("$arg", action_exp, 4))
1490 {
1491 add_local_symbols (collect, t->address, 'A');
6156728b 1492 action_exp = strchr (action_exp, ','); /* more? */
6a02d201
MS
1493 }
1494 else if (0 == strncasecmp ("$loc", action_exp, 4))
1495 {
1496 add_local_symbols (collect, t->address, 'L');
6156728b
MS
1497 action_exp = strchr (action_exp, ','); /* more? */
1498 }
6a02d201
MS
1499 else
1500 {
1501 unsigned long addr, len;
9fe11cd1
MS
1502 struct cleanup *old_chain = NULL;
1503 struct cleanup *old_chain1 = NULL;
1504 struct agent_reqs areqs;
6a02d201
MS
1505
1506 exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
ad3b8c4a
JM
1507 old_chain = make_cleanup ((make_cleanup_func)
1508 free_current_contents, &exp);
9fe11cd1 1509
8d6476c7
MS
1510 switch (exp->elts[0].opcode) {
1511 case OP_REGISTER:
1512 i = exp->elts[1].longconst;
1513 if (info_verbose)
1514 printf_filtered ("OP_REGISTER: ");
1515 add_register (collect, i);
1516 break;
1517
1518 case UNOP_MEMVAL:
1519 /* safe because we know it's a simple expression */
1520 tempval = evaluate_expression (exp);
1521 addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
1522 len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
1523 add_memrange (collect, -1, addr, len);
1524 break;
1525
1526 case OP_VAR_VALUE:
1527 collect_symbol (collect, exp->elts[2].symbol);
1528 break;
1529
1530 default: /* full-fledged expression */
1531 aexpr = gen_trace_for_expr (exp);
1532
ad3b8c4a
JM
1533 old_chain1 = make_cleanup ((make_cleanup_func)
1534 free_agent_expr, aexpr);
8d6476c7
MS
1535
1536 ax_reqs (aexpr, &areqs);
1537 if (areqs.flaw != agent_flaw_none)
1538 error ("malformed expression");
1539
1540 if (areqs.min_height < 0)
1541 error ("gdb: Internal error: expression has min height < 0");
1542 if (areqs.max_height > 20)
1543 error ("expression too complicated, try simplifying");
1544
1545 discard_cleanups (old_chain1);
1546 add_aexpr (collect, aexpr);
1547
1548 /* take care of the registers */
1549 if (areqs.reg_mask_len > 0)
1550 {
1551 int ndx1;
1552 int ndx2;
1553
1554 for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
1555 {
1556 QUIT; /* allow user to bail out with ^C */
1557 if (areqs.reg_mask[ndx1] != 0)
1558 {
1559 /* assume chars have 8 bits */
1560 for (ndx2 = 0; ndx2 < 8; ndx2++)
1561 if (areqs.reg_mask[ndx1] & (1 << ndx2))
1562 /* it's used -- record it */
1563 add_register (collect, ndx1 * 8 + ndx2);
1564 }
1565 }
1566 }
1567 break;
1568 } /* switch */
9fe11cd1 1569 do_cleanups (old_chain);
8d6476c7 1570 } /* do */
6a02d201 1571 } while (action_exp && *action_exp++ == ',');
8d6476c7 1572 } /* if */
728c7f37 1573 else if (cmd->function.cfunc == while_stepping_pseudocommand)
6a02d201
MS
1574 {
1575 collect = &stepping_list;
1576 }
728c7f37 1577 else if (cmd->function.cfunc == end_actions_pseudocommand)
6a02d201
MS
1578 {
1579 if (collect == &stepping_list) /* end stepping actions */
1580 collect = &tracepoint_list;
1581 else
1582 break; /* end tracepoint actions */
1583 }
8d6476c7 1584 } /* for */
6a02d201
MS
1585 memrange_sortmerge (&tracepoint_list);
1586 memrange_sortmerge (&stepping_list);
1587
9fe11cd1
MS
1588 *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
1589 *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
6a02d201
MS
1590}
1591
9fe11cd1
MS
1592static void
1593add_aexpr(collect, aexpr)
1594 struct collection_list *collect;
1595 struct agent_expr *aexpr;
1596{
1597 if (collect->next_aexpr_elt >= collect->aexpr_listsize)
1598 {
1599 collect->aexpr_list =
1600 xrealloc (collect->aexpr_list,
1601 2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
1602 collect->aexpr_listsize *= 2;
1603 }
1604 collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
1605 collect->next_aexpr_elt++;
1606}
1607
6a02d201
MS
1608static char target_buf[2048];
1609
0745a748
MS
1610/* Set "transparent" memory ranges
1611
1612 Allow trace mechanism to treat text-like sections
1613 (and perhaps all read-only sections) transparently,
1614 i.e. don't reject memory requests from these address ranges
1615 just because they haven't been collected. */
1616
1617static void
1618remote_set_transparent_ranges (void)
1619{
1620 extern bfd *exec_bfd;
1621 asection *s;
1622 bfd_size_type size;
1623 bfd_vma lma;
1624 int anysecs = 0;
1625
1626 if (!exec_bfd)
1627 return; /* no information to give. */
1628
1629 strcpy (target_buf, "QTro");
1630 for (s = exec_bfd->sections; s; s = s->next)
1631 {
1632 char tmp[40];
1633
1634 if ((s->flags & SEC_LOAD) == 0 ||
1635 /* (s->flags & SEC_CODE) == 0 || */
1636 (s->flags & SEC_READONLY) == 0)
1637 continue;
1638
1639 anysecs = 1;
1640 lma = s->lma;
1641 size = bfd_get_section_size_before_reloc (s);
1642 sprintf (tmp, ":%x,%x", lma, lma + size);
1643 strcat (target_buf, tmp);
1644 }
1645 if (anysecs)
1646 {
1647 putpkt (target_buf);
1648 getpkt (target_buf, 0);
1649 }
1650}
1651
8b9c29f5
MS
1652/* tstart command:
1653
9fe11cd1 1654 Tell target to clear any previous trace experiment.
8b9c29f5
MS
1655 Walk the list of tracepoints, and send them (and their actions)
1656 to the target. If no errors,
1657 Tell target to start a new trace experiment. */
1658
6a02d201
MS
1659static void
1660trace_start_command (args, from_tty)
1661 char *args;
1662 int from_tty;
1663{ /* STUB_COMM MOSTLY_IMPLEMENTED */
1664 struct tracepoint *t;
1665 char buf[2048];
9fe11cd1
MS
1666 char **tdp_actions;
1667 char **stepping_actions;
1668 int ndx;
1669 struct cleanup *old_chain = NULL;
6a02d201
MS
1670
1671 dont_repeat (); /* like "run", dangerous to repeat accidentally */
1672
1673 if (target_is_remote ())
1674 {
1675 putpkt ("QTinit");
1676 remote_get_noisy_reply (target_buf);
1677 if (strcmp (target_buf, "OK"))
1678 error ("Target does not support this command.");
1679
1680 ALL_TRACEPOINTS (t)
1681 {
1682 int ss_count; /* if actions include singlestepping */
1683 int disable_mask; /* ??? */
1684 int enable_mask; /* ??? */
1685
1686 sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address,
1687 t->enabled == enabled ? 'E' : 'D',
1688 t->step_count, t->pass_count);
9fe11cd1
MS
1689
1690 if (t->actions)
1691 strcat (buf, "-");
1692 putpkt (buf);
1693 remote_get_noisy_reply (target_buf);
1694 if (strcmp (target_buf, "OK"))
1695 error ("Target does not support tracepoints.");
1696
6a02d201
MS
1697 if (t->actions)
1698 {
9fe11cd1
MS
1699 encode_actions (t, &tdp_actions, &stepping_actions);
1700 old_chain = make_cleanup (free_actions_list, tdp_actions);
1701 (void) make_cleanup (free_actions_list, stepping_actions);
1702
6a02d201
MS
1703 /* do_single_steps (t); */
1704 if (tdp_actions)
1705 {
9fe11cd1
MS
1706 for (ndx = 0; tdp_actions[ndx]; ndx++)
1707 {
1708 QUIT; /* allow user to bail out with ^C */
1709 sprintf (buf, "QTDP:-%x:%x:%s%c",
1710 t->number, t->address,
1711 tdp_actions[ndx],
1712 ((tdp_actions[ndx+1] || stepping_actions)
1713 ? '-' : 0));
1714 putpkt (buf);
1715 remote_get_noisy_reply (target_buf);
1716 if (strcmp (target_buf, "OK"))
1717 error ("Error on target while setting tracepoints.");
1718 }
6a02d201
MS
1719 }
1720 if (stepping_actions)
1721 {
9fe11cd1
MS
1722 for (ndx = 0; stepping_actions[ndx]; ndx++)
1723 {
1724 QUIT; /* allow user to bail out with ^C */
1725 sprintf (buf, "QTDP:-%x:%x:%s%s%s",
1726 t->number, t->address,
1727 ((ndx == 0) ? "S" : ""),
1728 stepping_actions[ndx],
1729 (stepping_actions[ndx+1] ? "-" : ""));
1730 putpkt (buf);
1731 remote_get_noisy_reply (target_buf);
1732 if (strcmp (target_buf, "OK"))
1733 error ("Error on target while setting tracepoints.");
1734 }
6a02d201 1735 }
9fe11cd1
MS
1736
1737 do_cleanups (old_chain);
6a02d201 1738 }
6a02d201 1739 }
0745a748
MS
1740 /* Tell target to treat text-like sections as transparent */
1741 remote_set_transparent_ranges ();
1742 /* Now insert traps and begin collecting data */
6a02d201
MS
1743 putpkt ("QTStart");
1744 remote_get_noisy_reply (target_buf);
1745 if (strcmp (target_buf, "OK"))
1746 error ("Bogus reply from target: %s", target_buf);
6156728b
MS
1747 set_traceframe_num (-1); /* all old traceframes invalidated */
1748 set_tracepoint_num (-1);
1749 set_traceframe_context(-1);
57a39824 1750 trace_running_p = 1;
6a02d201
MS
1751 }
1752 else
9fe11cd1 1753 error ("Trace can only be run on remote targets.");
6a02d201
MS
1754}
1755
8b9c29f5 1756/* tstop command */
6a02d201
MS
1757static void
1758trace_stop_command (args, from_tty)
1759 char *args;
1760 int from_tty;
1761{ /* STUB_COMM IS_IMPLEMENTED */
1762 if (target_is_remote ())
1763 {
1764 putpkt ("QTStop");
1765 remote_get_noisy_reply (target_buf);
1766 if (strcmp (target_buf, "OK"))
1767 error ("Bogus reply from target: %s", target_buf);
57a39824 1768 trace_running_p = 0;
6a02d201
MS
1769 }
1770 else
1771 error ("Trace can only be run on remote targets.");
1772}
1773
41158958
EZ
1774unsigned long trace_running_p;
1775
8b9c29f5 1776/* tstatus command */
6a02d201
MS
1777static void
1778trace_status_command (args, from_tty)
1779 char *args;
1780 int from_tty;
1781{ /* STUB_COMM IS_IMPLEMENTED */
1782 if (target_is_remote ())
1783 {
1784 putpkt ("qTStatus");
1785 remote_get_noisy_reply (target_buf);
41158958
EZ
1786
1787 if (target_buf[0] != 'T' ||
9fe11cd1
MS
1788 (target_buf[1] != '0' && target_buf[1] != '1'))
1789 error ("Bogus reply from target: %s", target_buf);
1790
41158958
EZ
1791 /* exported for use by the GUI */
1792 trace_running_p = (target_buf[1] == '1');
6a02d201
MS
1793 }
1794 else
1795 error ("Trace can only be run on remote targets.");
1796}
1797
8b9c29f5 1798/* Worker function for the various flavors of the tfind command */
6156728b 1799static void
c677110c
MS
1800finish_tfind_command (msg, from_tty)
1801 char *msg;
6156728b
MS
1802 int from_tty;
1803{
1804 int target_frameno = -1, target_tracept = -1;
c677110c
MS
1805 CORE_ADDR old_frame_addr;
1806 struct symbol *old_func;
1807 char *reply;
1808
1809 old_frame_addr = FRAME_FP (get_current_frame ());
1810 old_func = find_pc_function (read_pc ());
1811
1812 putpkt (msg);
1813 reply = remote_get_noisy_reply (msg);
6156728b
MS
1814
1815 while (reply && *reply)
1816 switch (*reply) {
1817 case 'F':
74c1b0ba 1818 if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
8b9c29f5
MS
1819 {
1820 /* A request for a non-existant trace frame has failed.
1821 Our response will be different, depending on FROM_TTY:
1822
1823 If FROM_TTY is true, meaning that this command was
1824 typed interactively by the user, then give an error
1825 and DO NOT change the state of traceframe_number etc.
1826
1827 However if FROM_TTY is false, meaning that we're either
1828 in a script, a loop, or a user-defined command, then
1829 DON'T give an error, but DO change the state of
1830 traceframe_number etc. to invalid.
1831
1832 The rationalle is that if you typed the command, you
1833 might just have committed a typo or something, and you'd
1834 like to NOT lose your current debugging state. However
1835 if you're in a user-defined command or especially in a
1836 loop, then you need a way to detect that the command
1837 failed WITHOUT aborting. This allows you to write
1838 scripts that search thru the trace buffer until the end,
1839 and then continue on to do something else. */
1840
1841 if (from_tty)
1842 error ("Target failed to find requested trace frame.");
1843 else
1844 {
1845 if (info_verbose)
1846 printf_filtered ("End of trace buffer.\n");
1847 /* The following will not recurse, since it's special-cased */
1848 trace_find_command ("-1", from_tty);
c677110c
MS
1849 reply = NULL; /* break out of loop,
1850 (avoid recursive nonsense) */
8b9c29f5
MS
1851 }
1852 }
6156728b
MS
1853 break;
1854 case 'T':
74c1b0ba 1855 if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
6156728b
MS
1856 error ("Target failed to find requested trace frame.");
1857 break;
1858 case 'O': /* "OK"? */
1859 if (reply[1] == 'K' && reply[2] == '\0')
1860 reply += 2;
1861 else
1862 error ("Bogus reply from target: %s", reply);
1863 break;
1864 default:
1865 error ("Bogus reply from target: %s", reply);
1866 }
1867
1868 flush_cached_frames ();
1869 registers_changed ();
1870 select_frame (get_current_frame (), 0);
1871 set_traceframe_num (target_frameno);
1872 set_tracepoint_num (target_tracept);
c677110c
MS
1873 if (target_frameno == -1)
1874 set_traceframe_context (-1);
1875 else
1876 set_traceframe_context (read_pc ());
6156728b
MS
1877
1878 if (from_tty)
c677110c
MS
1879 {
1880 int source_only;
1881
99fa2de0
MS
1882 /* NOTE: in immitation of the step command, try to determine
1883 whether we have made a transition from one function to another.
1884 If so, we'll print the "stack frame" (ie. the new function and
1885 it's arguments) -- otherwise we'll just show the new source line.
1886
1887 This determination is made by checking (1) whether the current
1888 function has changed, and (2) whether the current FP has changed.
1889 Hack: if the FP wasn't collected, either at the current or the
1890 previous frame, assume that the FP has NOT changed. */
1891
1892 if (old_func == find_pc_function (read_pc ()) &&
1893 (old_frame_addr == 0 ||
1894 FRAME_FP (get_current_frame ()) == 0 ||
1895 old_frame_addr == FRAME_FP (get_current_frame ())))
c677110c
MS
1896 source_only = -1;
1897 else
1898 source_only = 1;
1899
1900 print_stack_frame (selected_frame, selected_frame_level, source_only);
1901 do_displays ();
1902 }
6156728b
MS
1903}
1904
1905/* trace_find_command takes a trace frame number n,
1906 sends "QTFrame:<n>" to the target,
1907 and accepts a reply that may contain several optional pieces
1908 of information: a frame number, a tracepoint number, and an
1909 indication of whether this is a trap frame or a stepping frame.
1910
1911 The minimal response is just "OK" (which indicates that the
1912 target does not give us a frame number or a tracepoint number).
1913 Instead of that, the target may send us a string containing
1914 any combination of:
1915 F<hexnum> (gives the selected frame number)
1916 T<hexnum> (gives the selected tracepoint number)
1917 */
1918
8b9c29f5 1919/* tfind command */
6a02d201
MS
1920static void
1921trace_find_command (args, from_tty)
1922 char *args;
1923 int from_tty;
1924{ /* STUB_COMM PART_IMPLEMENTED */
1925 /* this should only be called with a numeric argument */
6156728b 1926 int frameno = -1;
6156728b
MS
1927 char *tmp;
1928
6a02d201
MS
1929 if (target_is_remote ())
1930 {
1931 if (args == 0 || *args == 0)
6156728b
MS
1932 { /* TFIND with no args means find NEXT trace frame. */
1933 if (traceframe_number == -1)
1934 frameno = 0; /* "next" is first one */
1935 else
1936 frameno = traceframe_number + 1;
1937 }
1938 else if (0 == strcmp (args, "-"))
1939 {
1940 if (traceframe_number == -1)
1941 error ("not debugging trace buffer");
bf1aae13 1942 else if (from_tty && traceframe_number == 0)
6156728b
MS
1943 error ("already at start of trace buffer");
1944
1945 frameno = traceframe_number - 1;
1946 }
6a02d201 1947 else
6156728b 1948 frameno = parse_and_eval_address (args);
6a02d201 1949
9fe11cd1
MS
1950 if (frameno < -1)
1951 error ("invalid input (%d is less than zero)", frameno);
6156728b 1952
9fe11cd1 1953 sprintf (target_buf, "QTFrame:%x", frameno);
c677110c 1954 finish_tfind_command (target_buf, from_tty);
6a02d201
MS
1955 }
1956 else
1957 error ("Trace can only be run on remote targets.");
1958}
1959
8b9c29f5 1960/* tfind end */
6156728b
MS
1961static void
1962trace_find_end_command (args, from_tty)
1963 char *args;
1964 int from_tty;
1965{
1966 trace_find_command ("-1", from_tty);
1967}
1968
8b9c29f5 1969/* tfind none */
6156728b
MS
1970static void
1971trace_find_none_command (args, from_tty)
1972 char *args;
1973 int from_tty;
1974{
1975 trace_find_command ("-1", from_tty);
1976}
1977
8b9c29f5 1978/* tfind start */
6156728b
MS
1979static void
1980trace_find_start_command (args, from_tty)
1981 char *args;
1982 int from_tty;
1983{
1984 trace_find_command ("0", from_tty);
1985}
1986
8b9c29f5 1987/* tfind pc command */
6a02d201
MS
1988static void
1989trace_find_pc_command (args, from_tty)
1990 char *args;
1991 int from_tty;
1992{ /* STUB_COMM PART_IMPLEMENTED */
1993 CORE_ADDR pc;
6156728b 1994 char *tmp;
6a02d201
MS
1995
1996 if (target_is_remote ())
1997 {
1998 if (args == 0 || *args == 0)
6156728b
MS
1999 pc = read_pc (); /* default is current pc */
2000 else
2001 pc = parse_and_eval_address (args);
6a02d201 2002
6156728b 2003 sprintf (target_buf, "QTFrame:pc:%x", pc);
c677110c 2004 finish_tfind_command (target_buf, from_tty);
6a02d201
MS
2005 }
2006 else
2007 error ("Trace can only be run on remote targets.");
2008}
2009
8b9c29f5 2010/* tfind tracepoint command */
6a02d201 2011static void
6156728b 2012trace_find_tracepoint_command (args, from_tty)
6a02d201
MS
2013 char *args;
2014 int from_tty;
2015{ /* STUB_COMM PART_IMPLEMENTED */
74c1b0ba 2016 int tdp;
6a02d201
MS
2017 char buf[40], *tmp;
2018
2019 if (target_is_remote ())
2020 {
2021 if (args == 0 || *args == 0)
6156728b
MS
2022 if (tracepoint_number == -1)
2023 error ("No current tracepoint -- please supply an argument.");
2024 else
2025 tdp = tracepoint_number; /* default is current TDP */
2026 else
2027 tdp = parse_and_eval_address (args);
6a02d201 2028
6156728b 2029 sprintf (target_buf, "QTFrame:tdp:%x", tdp);
c677110c 2030 finish_tfind_command (target_buf, from_tty);
6a02d201
MS
2031 }
2032 else
2033 error ("Trace can only be run on remote targets.");
2034}
2035
6156728b 2036/* TFIND LINE command:
8b9c29f5
MS
2037
2038 This command will take a sourceline for argument, just like BREAK
2039 or TRACE (ie. anything that "decode_line_1" can handle).
2040
2041 With no argument, this command will find the next trace frame
2042 corresponding to a source line OTHER THAN THE CURRENT ONE. */
6156728b 2043
6a02d201 2044static void
6156728b 2045trace_find_line_command (args, from_tty)
6a02d201
MS
2046 char *args;
2047 int from_tty;
2048{ /* STUB_COMM PART_IMPLEMENTED */
6156728b
MS
2049 static CORE_ADDR start_pc, end_pc;
2050 struct symtabs_and_lines sals;
2051 struct symtab_and_line sal;
6156728b
MS
2052 char *tmp;
2053 struct cleanup *old_chain;
6a02d201
MS
2054
2055 if (target_is_remote ())
2056 {
6156728b
MS
2057 if (args == 0 || *args == 0)
2058 {
2059 sal = find_pc_line ((get_current_frame ())->pc, 0);
2060 sals.nelts = 1;
2061 sals.sals = (struct symtab_and_line *)
2062 xmalloc (sizeof (struct symtab_and_line));
2063 sals.sals[0] = sal;
6a02d201 2064 }
6156728b 2065 else
6a02d201 2066 {
6156728b
MS
2067 sals = decode_line_spec (args, 1);
2068 sal = sals.sals[0];
6a02d201
MS
2069 }
2070
6156728b
MS
2071 old_chain = make_cleanup (free, sals.sals);
2072 if (sal.symtab == 0)
2073 {
2074 printf_filtered ("TFIND: No line number information available");
2075 if (sal.pc != 0)
2076 {
2077 /* This is useful for "info line *0x7f34". If we can't tell the
2078 user about a source line, at least let them have the symbolic
2079 address. */
2080 printf_filtered (" for address ");
2081 wrap_here (" ");
2082 print_address (sal.pc, gdb_stdout);
2083 printf_filtered (";\n -- will attempt to find by PC. \n");
2084 }
2085 else
2086 {
2087 printf_filtered (".\n");
2088 return; /* no line, no PC; what can we do? */
2089 }
2090 }
2091 else if (sal.line > 0
2092 && find_line_pc_range (sal, &start_pc, &end_pc))
2093 {
2094 if (start_pc == end_pc)
2095 {
2096 printf_filtered ("Line %d of \"%s\"",
2097 sal.line, sal.symtab->filename);
2098 wrap_here (" ");
2099 printf_filtered (" is at address ");
2100 print_address (start_pc, gdb_stdout);
2101 wrap_here (" ");
2102 printf_filtered (" but contains no code.\n");
2103 sal = find_pc_line (start_pc, 0);
2104 if (sal.line > 0 &&
2105 find_line_pc_range (sal, &start_pc, &end_pc) &&
2106 start_pc != end_pc)
2107 printf_filtered ("Attempting to find line %d instead.\n",
2108 sal.line);
2109 else
2110 error ("Cannot find a good line.");
2111 }
2112 }
2113 else
2114 /* Is there any case in which we get here, and have an address
2115 which the user would want to see? If we have debugging symbols
2116 and no line numbers? */
2117 error ("Line number %d is out of range for \"%s\".\n",
2118 sal.line, sal.symtab->filename);
2119
2120 if (args && *args) /* find within range of stated line */
2121 sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
2122 else /* find OUTSIDE OF range of CURRENT line */
2123 sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
c677110c 2124 finish_tfind_command (target_buf, from_tty);
6156728b 2125 do_cleanups (old_chain);
6a02d201
MS
2126 }
2127 else
2128 error ("Trace can only be run on remote targets.");
2129}
2130
8b9c29f5 2131/* tfind range command */
6a02d201 2132static void
6156728b 2133trace_find_range_command (args, from_tty)
6a02d201
MS
2134 char *args;
2135 int from_tty;
2136{ /* STUB_COMM PART_IMPLEMENTED */
6156728b 2137 static CORE_ADDR start, stop;
6156728b 2138 char *tmp;
6a02d201
MS
2139
2140 if (target_is_remote ())
2141 {
6156728b 2142 if (args == 0 || *args == 0)
6a02d201 2143 { /* XXX FIXME: what should default behavior be? */
6156728b 2144 printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
6a02d201
MS
2145 return;
2146 }
2147
6156728b 2148 if (0 != (tmp = strchr (args, ',' )))
6a02d201 2149 {
6156728b
MS
2150 *tmp++ = '\0'; /* terminate start address */
2151 while (isspace (*tmp))
2152 tmp++;
2153 start = parse_and_eval_address (args);
2154 stop = parse_and_eval_address (tmp);
2155 }
2156 else
2157 { /* no explicit end address? */
2158 start = parse_and_eval_address (args);
2159 stop = start + 1; /* ??? */
6a02d201
MS
2160 }
2161
6156728b 2162 sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
c677110c 2163 finish_tfind_command (target_buf, from_tty);
6a02d201
MS
2164 }
2165 else
2166 error ("Trace can only be run on remote targets.");
2167}
2168
8b9c29f5 2169/* tfind outside command */
6a02d201 2170static void
6156728b 2171trace_find_outside_command (args, from_tty)
6a02d201
MS
2172 char *args;
2173 int from_tty;
6156728b
MS
2174{ /* STUB_COMM PART_IMPLEMENTED */
2175 CORE_ADDR start, stop;
6156728b
MS
2176 char *tmp;
2177
2178 if (target_is_remote ())
6a02d201 2179 {
6156728b
MS
2180 if (args == 0 || *args == 0)
2181 { /* XXX FIXME: what should default behavior be? */
2182 printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
2183 return;
2184 }
6a02d201 2185
6156728b
MS
2186 if (0 != (tmp = strchr (args, ',' )))
2187 {
2188 *tmp++ = '\0'; /* terminate start address */
2189 while (isspace (*tmp))
2190 tmp++;
2191 start = parse_and_eval_address (args);
2192 stop = parse_and_eval_address (tmp);
2193 }
2194 else
2195 { /* no explicit end address? */
2196 start = parse_and_eval_address (args);
2197 stop = start + 1; /* ??? */
2198 }
2199
2200 sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
c677110c 2201 finish_tfind_command (target_buf, from_tty);
6156728b 2202 }
6a02d201 2203 else
6156728b 2204 error ("Trace can only be run on remote targets.");
6a02d201
MS
2205}
2206
8b9c29f5 2207/* save-tracepoints command */
6a02d201
MS
2208static void
2209tracepoint_save_command (args, from_tty)
2210 char *args;
2211 int from_tty;
2212{
2213 struct tracepoint *tp;
2214 struct action_line *line;
2215 FILE *fp;
2216 char *i1 = " ", *i2 = " ";
2217 char *indent, *actionline;
2218
2219 if (args == 0 || *args == 0)
2220 error ("Argument required (file name in which to save tracepoints");
2221
2222 if (tracepoint_chain == 0)
2223 {
2224 warning ("save-tracepoints: no tracepoints to save.\n");
2225 return;
2226 }
2227
2228 if (!(fp = fopen (args, "w")))
2229 error ("Unable to open file '%s' for saving tracepoints");
2230
2231 ALL_TRACEPOINTS (tp)
2232 {
2233 if (tp->addr_string)
2234 fprintf (fp, "trace %s\n", tp->addr_string);
2235 else
2236 fprintf (fp, "trace *0x%x\n", tp->address);
2237
2238 if (tp->pass_count)
2239 fprintf (fp, " passcount %d\n", tp->pass_count);
2240
2241 if (tp->actions)
2242 {
2243 fprintf (fp, " actions\n");
2244 indent = i1;
2245 for (line = tp->actions; line; line = line->next)
2246 {
728c7f37
MS
2247 struct cmd_list_element *cmd;
2248
9fe11cd1 2249 QUIT; /* allow user to bail out with ^C */
6a02d201
MS
2250 actionline = line->action;
2251 while (isspace(*actionline))
2252 actionline++;
2253
2254 fprintf (fp, "%s%s\n", indent, actionline);
5d187fd3
MS
2255 if (*actionline != '#') /* skip for comment lines */
2256 {
2257 cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
2258 if (cmd == 0)
2259 error ("Bad action list item: %s", actionline);
2260 if (cmd->function.cfunc == while_stepping_pseudocommand)
2261 indent = i2;
2262 else if (cmd->function.cfunc == end_actions_pseudocommand)
2263 indent = i1;
2264 }
6a02d201
MS
2265 }
2266 }
2267 }
2268 fclose (fp);
2269 if (from_tty)
2270 printf_filtered ("Tracepoints saved to file '%s'.\n", args);
2271 return;
2272}
2273
8b9c29f5 2274/* info scope command: list the locals for a scope. */
6a02d201
MS
2275static void
2276scope_info (args, from_tty)
2277 char *args;
2278 int from_tty;
2279{
2280 struct symtab_and_line sal;
2281 struct symtabs_and_lines sals;
2282 struct symbol *sym;
6156728b 2283 struct minimal_symbol *msym;
6a02d201 2284 struct block *block;
6156728b 2285 char **canonical, *symname, *save_args = args;
6a02d201 2286 int i, nsyms, count = 0;
6a02d201
MS
2287
2288 if (args == 0 || *args == 0)
2289 error ("requires an argument (function, line or *addr) to define a scope");
2290
2291 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2292 if (sals.nelts == 0)
2293 return; /* presumably decode_line_1 has already warned */
2294
6156728b
MS
2295 /* Resolve line numbers to PC */
2296 resolve_sal_pc (&sals.sals[0]);
6a02d201 2297 block = block_for_pc (sals.sals[0].pc);
6156728b 2298
6a02d201
MS
2299 while (block != 0)
2300 {
9fe11cd1 2301 QUIT; /* allow user to bail out with ^C */
6a02d201
MS
2302 nsyms = BLOCK_NSYMS (block);
2303 for (i = 0; i < nsyms; i++)
2304 {
9fe11cd1 2305 QUIT; /* allow user to bail out with ^C */
6156728b
MS
2306 if (count == 0)
2307 printf_filtered ("Scope for %s:\n", save_args);
6a02d201
MS
2308 count++;
2309 sym = BLOCK_SYM (block, i);
6156728b
MS
2310 symname = SYMBOL_NAME (sym);
2311 if (symname == NULL || *symname == '\0')
2312 continue; /* probably botched, certainly useless */
2313
2314 printf_filtered ("Symbol %s is ", symname);
6a02d201
MS
2315 switch (SYMBOL_CLASS (sym)) {
2316 default:
2317 case LOC_UNDEF: /* messed up symbol? */
6156728b
MS
2318 printf_filtered ("a bogus symbol, class %d.\n",
2319 SYMBOL_CLASS (sym));
6a02d201
MS
2320 count--; /* don't count this one */
2321 continue;
6156728b
MS
2322 case LOC_CONST:
2323 printf_filtered ("a constant with value %d (0x%x)",
2324 SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
2325 break;
2326 case LOC_CONST_BYTES:
2327 printf_filtered ("constant bytes: ");
2328 if (SYMBOL_TYPE (sym))
2329 for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (sym)); i++)
2330 fprintf_filtered (gdb_stdout, " %02x",
2331 (unsigned) SYMBOL_VALUE_BYTES (sym) [i]);
2332 break;
2333 case LOC_STATIC:
2334 printf_filtered ("in static storage at address ");
2335 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2336 break;
2337 case LOC_REGISTER:
2338 printf_filtered ("a local variable in register $%s",
2339 reg_names [SYMBOL_VALUE (sym)]);
2340 break;
2341 case LOC_ARG:
2342 case LOC_LOCAL_ARG:
2343 printf_filtered ("an argument at stack/frame offset %ld",
2344 SYMBOL_VALUE (sym));
2345 break;
2346 case LOC_LOCAL:
2347 printf_filtered ("a local variable at frame offset %ld",
2348 SYMBOL_VALUE (sym));
2349 break;
2350 case LOC_REF_ARG:
2351 printf_filtered ("a reference argument at offset %ld",
2352 SYMBOL_VALUE (sym));
2353 break;
2354 case LOC_REGPARM:
2355 printf_filtered ("an argument in register $%s",
2356 reg_names[SYMBOL_VALUE (sym)]);
2357 break;
6a02d201 2358 case LOC_REGPARM_ADDR:
6156728b
MS
2359 printf_filtered ("the address of an argument, in register $%s",
2360 reg_names[SYMBOL_VALUE (sym)]);
2361 break;
2362 case LOC_TYPEDEF:
2363 printf_filtered ("a typedef.\n");
2364 continue;
2365 case LOC_LABEL:
2366 printf_filtered ("a label at address ");
2367 print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2368 break;
2369 case LOC_BLOCK:
2370 printf_filtered ("a function at address ");
2371 print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
2372 gdb_stdout);
2373 break;
2374 case LOC_BASEREG:
2375 printf_filtered ("a variable at offset %d from register $%s",
2376 SYMBOL_VALUE (sym),
2377 reg_names [SYMBOL_BASEREG (sym)]);
2378 break;
2379 case LOC_BASEREG_ARG:
2380 printf_filtered ("an argument at offset %d from register $%s",
2381 SYMBOL_VALUE (sym),
2382 reg_names [SYMBOL_BASEREG (sym)]);
2383 break;
6a02d201 2384 case LOC_UNRESOLVED:
6156728b
MS
2385 msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
2386 if (msym == NULL)
2387 printf_filtered ("Unresolved Static");
2388 else
2389 {
2390 printf_filtered ("static storage at address ");
2391 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1,
2392 gdb_stdout);
2393 }
2394 break;
2395 case LOC_OPTIMIZED_OUT:
2396 printf_filtered ("optimized out.\n");
2397 continue;
6a02d201 2398 }
6156728b
MS
2399 if (SYMBOL_TYPE (sym))
2400 printf_filtered (", length %d.\n",
2401 TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
6a02d201
MS
2402 }
2403 if (BLOCK_FUNCTION (block))
2404 break;
2405 else
2406 block = BLOCK_SUPERBLOCK (block);
2407 }
2408 if (count <= 0)
6156728b
MS
2409 printf_filtered ("Scope for %s contains no locals or arguments.\n",
2410 save_args);
6a02d201
MS
2411}
2412
8b9c29f5 2413/* worker function (cleanup) */
6156728b
MS
2414static void
2415replace_comma (comma)
2416 char *comma;
2417{
2418 *comma = ',';
2419}
2420
8b9c29f5 2421/* tdump command */
6156728b
MS
2422static void
2423trace_dump_command (args, from_tty)
2424 char *args;
2425 int from_tty;
2426{
2427 struct tracepoint *t;
2428 struct action_line *action;
2429 char *action_exp, *next_comma;
2430 struct cleanup *old_cleanups;
2431 int stepping_actions = 0;
2432 int stepping_frame = 0;
2433
9fe11cd1
MS
2434 if (!target_is_remote ())
2435 {
2436 error ("Trace can only be run on remote targets.");
2437 return;
2438 }
2439
6156728b
MS
2440 if (tracepoint_number == -1)
2441 {
2442 warning ("No current trace frame.");
2443 return;
2444 }
2445
2446 ALL_TRACEPOINTS (t)
2447 if (t->number == tracepoint_number)
2448 break;
2449
2450 if (t == NULL)
2451 error ("No known tracepoint matches 'current' tracepoint #%d.",
2452 tracepoint_number);
2453
2454 old_cleanups = make_cleanup (null_cleanup, NULL);
2455
2456 printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n",
2457 tracepoint_number, traceframe_number);
2458
2459 /* The current frame is a trap frame if the frame PC is equal
2460 to the tracepoint PC. If not, then the current frame was
2461 collected during single-stepping. */
2462
2463 stepping_frame = (t->address != read_pc());
2464
2465 for (action = t->actions; action; action = action->next)
2466 {
728c7f37
MS
2467 struct cmd_list_element *cmd;
2468
9fe11cd1 2469 QUIT; /* allow user to bail out with ^C */
6156728b
MS
2470 action_exp = action->action;
2471 while (isspace (*action_exp))
2472 action_exp++;
2473
2474 /* The collection actions to be done while stepping are
2475 bracketed by the commands "while-stepping" and "end". */
2476
5d187fd3
MS
2477 if (*action_exp == '#') /* comment line */
2478 continue;
2479
728c7f37
MS
2480 cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
2481 if (cmd == 0)
2482 error ("Bad action list item: %s", action_exp);
2483
2484 if (cmd->function.cfunc == while_stepping_pseudocommand)
6156728b 2485 stepping_actions = 1;
728c7f37 2486 else if (cmd->function.cfunc == end_actions_pseudocommand)
6156728b 2487 stepping_actions = 0;
728c7f37 2488 else if (cmd->function.cfunc == collect_pseudocommand)
6156728b
MS
2489 {
2490 /* Display the collected data.
2491 For the trap frame, display only what was collected at the trap.
2492 Likewise for stepping frames, display only what was collected
2493 while stepping. This means that the two boolean variables,
2494 STEPPING_FRAME and STEPPING_ACTIONS should be equal. */
2495 if (stepping_frame == stepping_actions)
2496 {
6156728b 2497 do { /* repeat over a comma-separated list */
9fe11cd1 2498 QUIT; /* allow user to bail out with ^C */
6156728b
MS
2499 if (*action_exp == ',')
2500 action_exp++;
2501 while (isspace (*action_exp))
2502 action_exp++;
2503
2504 next_comma = strchr (action_exp, ',');
6156728b
MS
2505
2506 if (0 == strncasecmp (action_exp, "$reg", 4))
2507 registers_info (NULL, from_tty);
2508 else if (0 == strncasecmp (action_exp, "$loc", 4))
2509 locals_info (NULL, from_tty);
2510 else if (0 == strncasecmp (action_exp, "$arg", 4))
2511 args_info (NULL, from_tty);
2512 else
28ad0632
MS
2513 { /* variable */
2514 if (next_comma)
2515 {
2516 make_cleanup (replace_comma, next_comma);
2517 *next_comma = '\0';
2518 }
6156728b
MS
2519 printf_filtered ("%s = ", action_exp);
2520 output_command (action_exp, from_tty);
2521 printf_filtered ("\n");
2522 }
2523 if (next_comma)
2524 *next_comma = ',';
2525 action_exp = next_comma;
2526 } while (action_exp && *action_exp == ',');
2527 }
2528 }
2529 }
2530 discard_cleanups (old_cleanups);
2531}
2532
9fe11cd1
MS
2533/* Convert the memory pointed to by mem into hex, placing result in buf.
2534 * Return a pointer to the last char put in buf (null)
2535 * "stolen" from sparc-stub.c
2536 */
2537
2538static const char hexchars[]="0123456789abcdef";
2539
2540static unsigned char *
2541mem2hex(mem, buf, count)
2542 unsigned char *mem;
2543 unsigned char *buf;
2544 int count;
2545{
2546 unsigned char ch;
2547
2548 while (count-- > 0)
2549 {
2550 ch = *mem++;
2551
2552 *buf++ = hexchars[ch >> 4];
2553 *buf++ = hexchars[ch & 0xf];
2554 }
2555
2556 *buf = 0;
2557
2558 return buf;
2559}
2560
2561int get_traceframe_number()
2562{
2563 return traceframe_number;
2564}
2565
2566
8b9c29f5 2567/* module initialization */
6a02d201
MS
2568void
2569_initialize_tracepoint ()
2570{
2571 tracepoint_chain = 0;
2572 tracepoint_count = 0;
6156728b
MS
2573 traceframe_number = -1;
2574 tracepoint_number = -1;
6a02d201
MS
2575
2576 set_internalvar (lookup_internalvar ("tpnum"),
2577 value_from_longest (builtin_type_int, (LONGEST) 0));
2578 set_internalvar (lookup_internalvar ("trace_frame"),
9fe11cd1 2579 value_from_longest (builtin_type_int, (LONGEST) -1));
6a02d201
MS
2580
2581 if (tracepoint_list.list == NULL)
2582 {
2583 tracepoint_list.listsize = 128;
9fe11cd1 2584 tracepoint_list.list = xmalloc
6a02d201
MS
2585 (tracepoint_list.listsize * sizeof (struct memrange));
2586 }
9fe11cd1
MS
2587 if (tracepoint_list.aexpr_list == NULL)
2588 {
2589 tracepoint_list.aexpr_listsize = 128;
2590 tracepoint_list.aexpr_list = xmalloc
2591 (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *));
2592 }
2593
6a02d201
MS
2594 if (stepping_list.list == NULL)
2595 {
2596 stepping_list.listsize = 128;
9fe11cd1 2597 stepping_list.list = xmalloc
6a02d201
MS
2598 (stepping_list.listsize * sizeof (struct memrange));
2599 }
2600
9fe11cd1
MS
2601 if (stepping_list.aexpr_list == NULL)
2602 {
2603 stepping_list.aexpr_listsize = 128;
2604 stepping_list.aexpr_list = xmalloc
2605 (stepping_list.aexpr_listsize * sizeof (struct agent_expr *));
2606 }
2607
6a02d201
MS
2608 add_info ("scope", scope_info,
2609 "List the variables local to a scope");
2610
6a02d201 2611 add_cmd ("tracepoints", class_trace, NO_FUNCTION,
6156728b 2612 "Tracing of program execution without stopping the program.",
6a02d201
MS
2613 &cmdlist);
2614
2615 add_info ("tracepoints", tracepoints_info,
6156728b
MS
2616 "Status of tracepoints, or tracepoint number NUMBER.\n\
2617Convenience variable \"$tpnum\" contains the number of the\n\
2618last tracepoint set.");
6a02d201
MS
2619
2620 add_info_alias ("tp", "tracepoints", 1);
2621
2622 add_com ("save-tracepoints", class_trace, tracepoint_save_command,
6156728b
MS
2623 "Save current tracepoint definitions as a script.\n\
2624Use the 'source' command in another debug session to restore them.");
6a02d201 2625
6156728b
MS
2626 add_com ("tdump", class_trace, trace_dump_command,
2627 "Print everything collected at the current tracepoint.");
6a02d201 2628
6156728b
MS
2629 add_prefix_cmd ("tfind", class_trace, trace_find_command,
2630 "Select a trace frame;\n\
2631No argument means forward by one frame; '-' meand backward by one frame.",
6a02d201
MS
2632 &tfindlist, "tfind ", 1, &cmdlist);
2633
2634 add_cmd ("outside", class_trace, trace_find_outside_command,
6156728b
MS
2635 "Select a trace frame whose PC is outside the given \
2636range.\nUsage: tfind outside addr1, addr2",
6a02d201
MS
2637 &tfindlist);
2638
2639 add_cmd ("range", class_trace, trace_find_range_command,
6156728b
MS
2640 "Select a trace frame whose PC is in the given range.\n\
2641Usage: tfind range addr1,addr2",
2642 &tfindlist);
6a02d201 2643
6156728b
MS
2644 add_cmd ("line", class_trace, trace_find_line_command,
2645 "Select a trace frame by source line.\n\
2646Argument can be a line number (with optional source file), \n\
2647a function name, or '*' followed by an address.\n\
2648Default argument is 'the next source line that was traced'.",
2649 &tfindlist);
2650
2651 add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
2652 "Select a trace frame by tracepoint number.\n\
2653Default is the tracepoint for the current trace frame.",
2654 &tfindlist);
6a02d201
MS
2655
2656 add_cmd ("pc", class_trace, trace_find_pc_command,
6156728b
MS
2657 "Select a trace frame by PC.\n\
2658Default is the current PC, or the PC of the current trace frame.",
2659 &tfindlist);
6a02d201 2660
6156728b
MS
2661 add_cmd ("end", class_trace, trace_find_end_command,
2662 "Synonym for 'none'.\n\
2663De-select any trace frame and resume 'live' debugging.",
2664 &tfindlist);
2665
2666 add_cmd ("none", class_trace, trace_find_none_command,
2667 "De-select any trace frame and resume 'live' debugging.",
2668 &tfindlist);
2669
2670 add_cmd ("start", class_trace, trace_find_start_command,
2671 "Select the first trace frame in the trace buffer.",
2672 &tfindlist);
6a02d201
MS
2673
2674 add_com ("tstatus", class_trace, trace_status_command,
6156728b 2675 "Display the status of the current trace data collection.");
6a02d201
MS
2676
2677 add_com ("tstop", class_trace, trace_stop_command,
2678 "Stop trace data collection.");
2679
2680 add_com ("tstart", class_trace, trace_start_command,
2681 "Start trace data collection.");
2682
2683 add_com ("passcount", class_trace, trace_pass_command,
6156728b
MS
2684 "Set the passcount for a tracepoint.\n\
2685The trace will end when the tracepoint has been passed 'count' times.\n\
2686Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2687if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2688
728c7f37 2689 add_com ("end", class_trace, end_actions_pseudocommand,
6156728b
MS
2690 "Ends a list of commands or actions.\n\
2691Several GDB commands allow you to enter a list of commands or actions.\n\
2692Entering \"end\" on a line by itself is the normal way to terminate\n\
2693such a list.\n\n\
2694Note: the \"end\" command cannot be used at the gdb prompt.");
2695
728c7f37 2696 add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
6156728b
MS
2697 "Specify single-stepping behavior at a tracepoint.\n\
2698Argument is number of instructions to trace in single-step mode\n\
2699following the tracepoint. This command is normally followed by\n\
2700one or more \"collect\" commands, to specify what to collect\n\
2701while single-stepping.\n\n\
2702Note: this command can only be used in a tracepoint \"actions\" list.");
2703
728c7f37
MS
2704 add_com_alias ("ws", "while-stepping", class_alias, 0);
2705 add_com_alias ("stepping", "while-stepping", class_alias, 0);
2706
2707 add_com ("collect", class_trace, collect_pseudocommand,
6156728b 2708 "Specify one or more data items to be collected at a tracepoint.\n\
9fe11cd1
MS
2709Accepts a comma-separated list of (one or more) expressions. GDB will\n\
2710collect all data (variables, registers) referenced by that expression.\n\
2711Also accepts the following special arguments:\n\
6156728b
MS
2712 $regs -- all registers.\n\
2713 $args -- all function arguments.\n\
2714 $locals -- all variables local to the block/function scope.\n\
6156728b 2715Note: this command can only be used in a tracepoint \"actions\" list.");
6a02d201
MS
2716
2717 add_com ("actions", class_trace, trace_actions_command,
6156728b
MS
2718 "Specify the actions to be taken at a tracepoint.\n\
2719Tracepoint actions may include collecting of specified data, \n\
2720single-stepping, or enabling/disabling other tracepoints, \n\
2721depending on target's capabilities.");
6a02d201
MS
2722
2723 add_cmd ("tracepoints", class_trace, delete_trace_command,
6156728b
MS
2724 "Delete specified tracepoints.\n\
2725Arguments are tracepoint numbers, separated by spaces.\n\
2726No argument means delete all tracepoints.",
6a02d201
MS
2727 &deletelist);
2728
2729 add_cmd ("tracepoints", class_trace, disable_trace_command,
6156728b
MS
2730 "Disable specified tracepoints.\n\
2731Arguments are tracepoint numbers, separated by spaces.\n\
2732No argument means disable all tracepoints.",
6a02d201
MS
2733 &disablelist);
2734
2735 add_cmd ("tracepoints", class_trace, enable_trace_command,
6156728b
MS
2736 "Enable specified tracepoints.\n\
2737Arguments are tracepoint numbers, separated by spaces.\n\
2738No argument means enable all tracepoints.",
6a02d201
MS
2739 &enablelist);
2740
2741 add_com ("trace", class_trace, trace_command,
6156728b
MS
2742 "Set a tracepoint at a specified line or function or address.\n\
2743Argument may be a line number, function name, or '*' plus an address.\n\
2744For a line number or function, trace at the start of its code.\n\
2745If an address is specified, trace at that exact address.\n\n\
2746Do \"help tracepoints\" for info on other tracepoint commands.");
6a02d201
MS
2747
2748 add_com_alias ("tp", "trace", class_alias, 0);
2749 add_com_alias ("tr", "trace", class_alias, 1);
2750 add_com_alias ("tra", "trace", class_alias, 1);
2751 add_com_alias ("trac", "trace", class_alias, 1);
6a02d201 2752}
6156728b 2753