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