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