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