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