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