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