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