]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/tracepoint.c
Some early changes by Keith Seitz to support the Tcl/Tk GUI.
[thirdparty/binutils-gdb.git] / gdb / tracepoint.c
CommitLineData
6a02d201
MS
1/* Tracing functionality for remote targets in custom GDB protocol
2 Copyright 1997 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "defs.h"
21#include "symtab.h"
22#include "frame.h"
23#include "tracepoint.h"
24#include "gdbtypes.h"
25#include "expression.h"
26#include "gdbcmd.h"
27#include "value.h"
28#include "target.h"
29#include "language.h"
30
31/* readline include files */
32#include "readline.h"
33#include "history.h"
34
35/* readline defines this. */
36#undef savestring
37
38#ifdef HAVE_UNISTD_H
39#include <unistd.h>
40#endif
41
42extern int info_verbose;
43
44/* If this definition isn't overridden by the header files, assume
45 that isatty and fileno exist on this system. */
46#ifndef ISATTY
47#define ISATTY(FP) (isatty (fileno (FP)))
48#endif
49
6a02d201
MS
50/* Chain of all tracepoints defined. */
51struct tracepoint *tracepoint_chain;
52
53/* Number of last tracepoint made. */
54static int tracepoint_count;
55
56/* Number of last traceframe collected. */
57static int traceframe_number;
58
59/* Utility: returns true if "target remote" */
60static int
61target_is_remote ()
62{
63 if (current_target.to_shortname &&
64 strcmp (current_target.to_shortname, "remote") == 0)
65 return 1;
66 else
67 return 0;
68}
69
70/* Utility: generate error from an incoming stub packet. */
71static void
72trace_error (buf)
73 char *buf;
74{
75 if (*buf++ != 'E')
76 return; /* not an error msg */
77 switch (*buf)
78 {
79 case '1': /* malformed packet error */
80 if (*++buf == '0') /* general case: */
81 error ("tracepoint.c: badly formed packet.");
82 else
83 error ("tracepoint.c: badly formed packet at field #%d.",
84 *buf - '0');
85 case '2':
86 error ("trace API error '%s'.", buf);
87 default:
88 error ("Target returns error code '%s'.", buf);
89 }
90}
91
92/* Obsolete: collect regs from a trace frame */
93static void
94trace_receive_regs (buf)
95 char *buf;
96{
97 long regno, i;
98 char regbuf[MAX_REGISTER_RAW_SIZE], *tmp, *p = buf;
99
100 while (*p)
101 {
102 regno = strtol (p, &tmp, 16);
103 if (p == tmp || *tmp++ != ':')
104 error ("tracepoint.c: malformed 'R' packet");
105 else p = tmp;
106
107 for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
108 {
109 if (p[0] == 0 || p[1] == 0)
110 warning ("Remote reply is too short: %s", buf);
111 regbuf[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
112 p += 2;
113 }
114
115 if (*p++ != ';')
116 error ("tracepoint.c: malformed 'R' packet");
117
118 supply_register (regno, regbuf);
119 }
120}
121
122/* Utility: wait for reply from stub, while accepting "O" packets */
123static void
124remote_get_noisy_reply (buf)
125 char *buf;
126{
127 do /* loop on reply from remote stub */
128 {
129 getpkt (buf, 0);
130 if (buf[0] == 0)
131 error ("Target does not support this command.");
132 else if (buf[0] == 'E')
133 trace_error (buf);
134 else if (buf[0] == 'R')
135 {
136 flush_cached_frames ();
137 registers_changed ();
138 select_frame (get_current_frame (), 0);
139 trace_receive_regs (buf);
140 }
141 else if (buf[0] == 'O' &&
142 buf[1] != 'K')
143 remote_console_output (buf + 1); /* 'O' message from stub */
144 else
145 return; /* here's the actual reply */
146 } while (1);
147}
148
149/* Set tracepoint count to NUM. */
150static void
151set_tracepoint_count (num)
152 int num;
153{
154 tracepoint_count = num;
155 set_internalvar (lookup_internalvar ("tpnum"),
156 value_from_longest (builtin_type_int, (LONGEST) num));
157}
158
159/* Set traceframe number to NUM. */
160static void
161set_traceframe_num (num)
162 int num;
163{
164 traceframe_number = num;
165 set_internalvar (lookup_internalvar ("trace_frame"),
166 value_from_longest (builtin_type_int, (LONGEST) num));
167}
168
169/* Low level routine to set a tracepoint.
170 Returns the tracepoint object so caller can set other things.
171 Does not set the tracepoint number!
172 Does not print anything.
173
174 ==> This routine should not be called if there is a chance of later
175 error(); otherwise it leaves a bogus tracepoint on the chain. Validate
176 your arguments BEFORE calling this routine! */
177
178static struct tracepoint *
179set_raw_tracepoint (sal)
180 struct symtab_and_line sal;
181{
182 register struct tracepoint *t, *tc;
183 struct cleanup *old_chain;
184
185 t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
186 old_chain = make_cleanup (free, t);
187 memset (t, 0, sizeof (*t));
188 t->address = sal.pc;
189 if (sal.symtab == NULL)
190 t->source_file = NULL;
191 else
57c0b026
MS
192 {
193 t->source_file = (char *) xmalloc (strlen (sal.symtab->filename) +
194 strlen (sal.symtab->dirname) + 1);
195
196 strcpy (t->source_file, sal.symtab->dirname);
197 strcat (t->source_file, sal.symtab->filename);
198 }
199
6a02d201
MS
200 t->language = current_language->la_language;
201 t->input_radix = input_radix;
202 t->line_number = sal.line;
203 t->enabled = enabled;
204 t->next = 0;
205 t->step_count = 0;
206 t->pass_count = 0;
207
208 /* Add this tracepoint to the end of the chain
209 so that a list of tracepoints will come out in order
210 of increasing numbers. */
211
212 tc = tracepoint_chain;
213 if (tc == 0)
214 tracepoint_chain = t;
215 else
216 {
217 while (tc->next)
218 tc = tc->next;
219 tc->next = t;
220 }
221 discard_cleanups (old_chain);
222 return t;
223}
224
225static void
226trace_command (arg, from_tty)
227 char *arg;
228 int from_tty;
229{
230 char **canonical = (char **)NULL;
231 struct symtabs_and_lines sals;
232 struct symtab_and_line sal;
233 struct tracepoint *t;
234 char *addr_start = 0, *addr_end = 0, *cond_start = 0, *cond_end = 0;
235 int i;
236
237 if (!arg || !*arg)
238 error ("trace command requires an argument");
239
240 if (from_tty && info_verbose)
241 printf_filtered ("TRACE %s\n", arg);
242
243 if (arg[0] == '/')
244 {
245 return;
246 }
247
248 addr_start = arg;
249 sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical);
250 addr_end = arg;
251 if (! sals.nelts)
252 return; /* ??? Presumably decode_line_1 has already warned? */
253
254 /* Resolve all line numbers to PC's */
255 for (i = 0; i < sals.nelts; i++)
256 resolve_sal_pc (&sals.sals[i]);
257
258 /* Now set all the tracepoints. */
259 for (i = 0; i < sals.nelts; i++)
260 {
261 sal = sals.sals[i];
262
263 t = set_raw_tracepoint (sal);
264 set_tracepoint_count (tracepoint_count + 1);
265 t->number = tracepoint_count;
266
267 /* If a canonical line spec is needed use that instead of the
57c0b026 268 command string. */
6a02d201 269 if (canonical != (char **)NULL && canonical[i] != NULL)
57c0b026 270 t->addr_string = canonical[i];
6a02d201 271 else if (addr_start)
57c0b026 272 t->addr_string = savestring (addr_start, addr_end - addr_start);
6a02d201 273 if (cond_start)
57c0b026
MS
274 t->cond_string = savestring (cond_start, cond_end - cond_start);
275
276 /* Let the UI know of any additions */
277 if (create_tracepoint_hook)
278 create_tracepoint_hook (t);
6a02d201
MS
279 }
280
281 if (sals.nelts > 1)
282 {
283 printf_filtered ("Multiple tracepoints were set.\n");
284 printf_filtered ("Use the \"delete\" command to delete unwanted tracepoints.\n");
285 }
286}
287
288static void
289tracepoints_info (tpnum_exp, from_tty)
290 char *tpnum_exp;
291 int from_tty;
292{
293 struct tracepoint *t;
294 struct action_line *action;
295 int found_a_tracepoint = 0;
296 char wrap_indent[80];
297 struct symbol *sym;
298 int tpnum = -1;
299#if 0
300 char *i1 = "\t", *i2 = "\t ";
301 char *indent, *actionline;;
302#endif
303
304 if (tpnum_exp)
305 tpnum = parse_and_eval_address (tpnum_exp);
306
307 ALL_TRACEPOINTS (t)
308 if (tpnum == -1 || tpnum == t->number)
309 {
310 extern int addressprint; /* print machine addresses? */
311
312 if (!found_a_tracepoint++)
313 printf_filtered (" *** [info tracepoints header line] ***\n");
314
315 strcpy (wrap_indent, " ");
316 if (addressprint)
317 strcat (wrap_indent, " ");
318
319 printf_filtered ("%-3d %-10s ", t->number,
320 t->enabled == enabled ? "enabled" : "disabled");
321 if (addressprint)
322 { /* FIXME-32x64: need a print_address_numeric with field width */
323 printf_filtered ("%s ", local_hex_string_custom ((unsigned long) t->address, "08l"));
324 }
325 if (t->source_file)
326 {
327 sym = find_pc_function (t->address);
328 if (sym)
329 {
330 fputs_filtered ("in ", gdb_stdout);
331 fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
332 wrap_here (wrap_indent);
333 fputs_filtered (" at ", gdb_stdout);
334 }
335 fputs_filtered (t->source_file, gdb_stdout);
336 printf_filtered (":%d", t->line_number);
337 }
338 else
339 print_address_symbolic (t->address, gdb_stdout, demangle, " ");
340
341 if (t->pass_count != 0)
342 printf_filtered (" passcount = %d", t->pass_count);
343 printf_filtered ("\n");
344 if (t->actions)
345 {
346 printf_filtered (" Actions for tracepoint %d: \n", t->number);
347/* indent = i1; */
348 for (action = t->actions; action; action = action->next)
349 {
350#if 0
351 actionline = action->action;
352 while (isspace(*actionline))
353 actionline++;
354
355 printf_filtered ("%s%s\n", indent, actionline);
356 if (0 == strncasecmp (actionline, "while-stepping", 14))
357 indent = i2;
358 else if (0 == strncasecmp (actionline, "end", 3))
359 indent = i1;
360#else
361 printf_filtered ("\t%s\n", action->action);
362#endif
363 }
364 }
365 }
366 if (!found_a_tracepoint)
367 {
368 if (tpnum == -1)
369 printf_filtered ("No tracepoints.\n");
370 else
371 printf_filtered ("No tracepoint number %d.\n", tpnum);
372 }
373}
374
375/* Optimization: the code to parse an enable, disable, or delete TP command
376 is virtually identical except for whether it performs an enable, disable,
377 or delete. Therefore I've combined them into one function with an opcode.
378 */
379enum tracepoint_opcode
380{
381 enable,
382 disable,
383 delete
384};
385
386/* This function implements enable, disable and delete. */
387static void
388tracepoint_operation (t, from_tty, opcode)
389 struct tracepoint *t;
390 int from_tty;
391 enum tracepoint_opcode opcode;
392{
393 struct tracepoint *t2;
394 struct action_line *action, *next;
395
396 switch (opcode) {
397 case enable:
398 t->enabled = enabled;
399 break;
400 case disable:
401 t->enabled = disabled;
402 break;
403 case delete:
404 if (tracepoint_chain == t)
405 tracepoint_chain = t->next;
406
407 ALL_TRACEPOINTS (t2)
408 if (t2->next == t)
409 {
410 t2->next = t->next;
411 break;
412 }
57c0b026
MS
413
414 /* Let the UI know of any deletions */
415 if (delete_tracepoint_hook)
416 delete_tracepoint_hook (t);
417
6a02d201
MS
418 if (t->cond_string)
419 free (t->cond_string);
420 if (t->addr_string)
421 free (t->addr_string);
422 if (t->source_file)
423 free (t->source_file);
424 for (action = t->actions; action; action = next)
425 {
426 next = action->next;
427 if (action->action)
428 free (action->action);
429 free (action);
430 }
431 free (t);
432 break;
433 }
434}
435
436/* Utility: parse a tracepoint number and look it up in the list. */
57c0b026 437struct tracepoint *
6a02d201
MS
438get_tracepoint_by_number (arg)
439 char **arg;
440{
441 struct tracepoint *t;
442 char *cp;
443 value_ptr val;
444 int tpnum;
445
446 if (arg == 0)
447 error ("Bad tracepoint argument");
448
449 if (*arg == 0 || **arg == 0) /* empty arg means refer to last tp */
450 tpnum = tracepoint_count;
451 else if (**arg == '$') /* handle convenience variable */
452 {
453 cp = *arg + 1;
454 /* find end of convenience variable name */
455 while (**arg && **arg != ' ' && **arg != '\t')
456 *arg++;
457 /* null-terminate if necessary */
458 if (**arg != 0)
459 *(*arg++) = 0;
460 val = value_of_internalvar (lookup_internalvar (cp));
461 if (TYPE_CODE( VALUE_TYPE (val)) != TYPE_CODE_INT)
462 error ("Convenience variable must have integral type.");
463 tpnum = (int) value_as_long (val);
464 }
465 else /* handle tracepoint number */
466 {
467 tpnum = strtol (*arg, arg, 10);
468 }
469 ALL_TRACEPOINTS (t)
470 if (t->number == tpnum)
471 {
472 return t;
473 }
474 warning ("No tracepoint number %d.\n", tpnum);
475 return NULL;
476}
477
478/* Utility: parse a list of tracepoint numbers, and call a func for each. */
479static void
480map_args_over_tracepoints (args, from_tty, opcode)
481 char *args;
482 int from_tty;
483 enum tracepoint_opcode opcode;
484{
485 struct tracepoint *t;
486 int tpnum;
487 char *cp;
488
489 if (args == 0 || *args == 0) /* do them all */
490 ALL_TRACEPOINTS (t)
491 tracepoint_operation (t, from_tty, opcode);
492 else
493 while (*args)
494 {
495 if (t = get_tracepoint_by_number (&args))
496 tracepoint_operation (t, from_tty, opcode);
497 while (*args == ' ' || *args == '\t')
498 args++;
499 }
500}
501
502static void
503enable_trace_command (args, from_tty)
504 char *args;
505 int from_tty;
506{
507 dont_repeat ();
508 map_args_over_tracepoints (args, from_tty, enable);
509}
510
511static void
512disable_trace_command (args, from_tty)
513 char *args;
514 int from_tty;
515{
516 dont_repeat ();
517 map_args_over_tracepoints (args, from_tty, disable);
518}
519
520static void
521delete_trace_command (args, from_tty)
522 char *args;
523 int from_tty;
524{
525 dont_repeat ();
526 if (!args || !*args)
527 if (!query ("Delete all tracepoints? "))
528 return;
529
530 map_args_over_tracepoints (args, from_tty, delete);
531}
532
533static void
534trace_pass_command (args, from_tty)
535 char *args;
536 int from_tty;
537{
538 struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
539 unsigned long count;
540
541 if (args == 0 || *args == 0)
542 error ("PASS command requires an argument (count + optional TP num)");
543
544 count = strtoul (args, &args, 10); /* count comes first, then TP num */
545
546 while (*args && isspace (*args))
547 args++;
548
549 if (*args && strncasecmp (args, "all", 3) == 0)
550 args += 3; /* skip special argument "all" */
551 else
552 t1 = get_tracepoint_by_number (&args);
553
554 if (t1 == NULL)
555 return; /* error, bad tracepoint number */
556
557 ALL_TRACEPOINTS (t2)
558 if (t1 == (struct tracepoint *) -1 || t1 == t2)
559 {
560 t2->pass_count = count;
561 if (from_tty)
562 printf_filtered ("Setting tracepoint %d's passcount to %d\n",
563 t2->number, count);
564 }
565}
566
567/* ACTIONS ACTIONS ACTIONS */
568
569static void read_actions PARAMS((struct tracepoint *));
570static void free_actions PARAMS((struct tracepoint *));
571static int validate_actionline PARAMS((char *, struct tracepoint *));
572
573static void
574trace_actions_command (args, from_tty)
575 char *args;
576 int from_tty;
577{
578 struct tracepoint *t;
579 char *actions;
580
581 if (t = get_tracepoint_by_number (&args))
582 {
583 if (from_tty)
584 printf_filtered ("Enter actions for tracepoint %d, one per line.\n",
585 t->number);
586 free_actions (t);
587 read_actions (t);
588 /* tracepoints_changed () */
589 }
590 /* else error, just return; */
591}
592
593enum actionline_type
594{
595 BADLINE = -1,
596 GENERIC = 0,
597 END = 1,
598 STEPPING = 2,
599};
600
601static void
602read_actions (t)
603 struct tracepoint *t;
604{
605 char *line;
606 char *prompt1 = "> ", *prompt2 = " > ";
607 char *prompt = prompt1;
608 enum actionline_type linetype;
609 extern FILE *instream;
610 struct action_line *next = NULL, *temp;
611 struct cleanup *old_chain;
612
613 /* Control-C quits instantly if typed while in this loop
614 since it should not wait until the user types a newline. */
615 immediate_quit++;
616#ifdef STOP_SIGNAL
617 if (job_control)
618 signal (STOP_SIGNAL, stop_sig);
619#endif
620 old_chain = make_cleanup (free_actions, (void *) t);
621 while (1)
622 {
623 /* Make sure that all output has been output. Some machines may let
624 you get away with leaving out some of the gdb_flush, but not all. */
625 wrap_here ("");
626 gdb_flush (gdb_stdout);
627 gdb_flush (gdb_stderr);
628 if (instream == stdin && ISATTY (instream))
629 line = readline (prompt);
630 else
631 line = gdb_readline (0);
632
633 linetype = validate_actionline (line, t);
634 if (linetype == BADLINE)
635 continue; /* already warned -- collect another line */
636
637 temp = xmalloc (sizeof (struct action_line));
638 temp->next = NULL;
639 temp->action = line;
640
641 if (next == NULL) /* first action for this tracepoint? */
642 t->actions = next = temp;
643 else
644 {
645 next->next = temp;
646 next = temp;
647 }
648
649 if (linetype == STEPPING) /* begin "while-stepping" */
650 if (prompt == prompt2)
651 {
652 warning ("Already processing 'while-stepping'");
653 continue;
654 }
655 else
656 prompt = prompt2; /* change prompt for stepping actions */
657 else if (linetype == END)
658 if (prompt == prompt2)
659 prompt = prompt1; /* end of single-stepping actions */
660 else
661 break; /* end of actions */
662 }
663#ifdef STOP_SIGNAL
664 if (job_control)
665 signal (STOP_SIGNAL, SIG_DFL);
666#endif
667 immediate_quit = 0;
668 discard_cleanups (old_chain);
669}
670
671static enum actionline_type
672validate_actionline (line, t)
673 char *line;
674 struct tracepoint *t;
675{
676 char *p;
677 struct expression *exp;
678 value_ptr temp, temp2;
679
680 for (p = line; isspace (*p); )
681 p++;
682
683 /* symbol lookup etc. */
684 if (*p == '\0') /* empty line: just prompt for another line. */
685 return BADLINE;
686 else if (0 == strncasecmp (p, "collect", 7))
687 {
688 p += 7;
689 do { /* repeat over a comma-separated list */
690 while (isspace (*p))
691 p++;
692
693 if (*p == '$' && /* look for special pseudo-symbols */
694 ((0 == strncasecmp ("reg", p + 1, 3)) ||
695 (0 == strncasecmp ("arg", p + 1, 3)) ||
696 (0 == strncasecmp ("loc", p + 1, 3))))
697 p = (char *) strchr (p, ',');
698 else
699 {
700 exp = parse_exp_1 (&p, block_for_pc (t->address), 1);
701 if (exp->elts[0].opcode != OP_VAR_VALUE &&
702 /*exp->elts[0].opcode != OP_LONG && */
703 /*exp->elts[0].opcode != UNOP_CAST && */
704 exp->elts[0].opcode != OP_REGISTER)
705 {
706 warning ("collect: enter variable name or register.\n");
707 return BADLINE;
708 }
709 if (exp->elts[0].opcode == OP_VAR_VALUE)
710 if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
711 {
712 warning ("%s is constant (value %d): will not be collected.",
713 SYMBOL_NAME (exp->elts[2].symbol),
714 SYMBOL_VALUE (exp->elts[2].symbol));
715 return BADLINE;
716 }
717 else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
718 {
719 warning ("%s is optimized away and cannot be collected.",
720 SYMBOL_NAME (exp->elts[2].symbol));
721 return BADLINE;
722 }
723 }
724 } while (p && *p++ == ',');
725 return GENERIC;
726 }
727 else if (0 == strncasecmp (p, "while-stepping", 14))
728 {
729 char *steparg; /* in case warning is necessary */
730
731 p += 14;
732 while (isspace (*p))
733 p++;
734 steparg = p;
735
736 if (*p)
737 {
738 t->step_count = strtol (p, &p, 0);
739 if (t->step_count == 0)
740 {
741 warning ("'%s' evaluates to zero -- command ignored.");
742 return BADLINE;
743 }
744 }
745 else
746 t->step_count = -1;
747 return STEPPING;
748 }
749 else if (0 == strncasecmp (p, "end", 3))
750 return END;
751 else
752 {
753 warning ("'%s' is not a supported tracepoint action.", p);
754 return BADLINE;
755 }
756}
757
758static void
759free_actions (t)
760 struct tracepoint *t;
761{
762 struct action_line *line, *next;
763
764 for (line = t->actions; line; line = next)
765 {
766 next = line->next;
767 free (line);
768 }
769 t->actions = NULL;
770}
771
772struct memrange {
773 int type; /* 0 for absolute memory range, else basereg number */
774 bfd_signed_vma start;
775 bfd_signed_vma end;
776};
777
778struct collection_list {
779 unsigned char regs_mask[8]; /* room for up to 256 regs */
780 long listsize;
781 long next_memrange;
782 struct memrange *list;
783} tracepoint_list, stepping_list;
784
785static int
786memrange_cmp (a, b)
787 struct memrange *a, *b;
788{
789 if (a->type < b->type) return -1;
790 if (a->type > b->type) return 1;
791 if (a->type == 0)
792 {
793 if ((bfd_vma) a->start < (bfd_vma) b->start) return -1;
794 if ((bfd_vma) a->start > (bfd_vma) b->start) return 1;
795 }
796 else
797 {
798 if (a->start < b->start) return -1;
799 if (a->start > b->start) return 1;
800 }
801 return 0;
802}
803
804static void
805memrange_sortmerge (memranges)
806 struct collection_list *memranges;
807{
808 int a, b;
809
810 qsort (memranges->list, memranges->next_memrange,
811 sizeof (struct memrange), memrange_cmp);
812 if (memranges->next_memrange > 0)
813 {
814 for (a = 0, b = 1; b < memranges->next_memrange; b++)
815 {
816 if (memranges->list[a].type == memranges->list[b].type &&
817 memranges->list[b].start - memranges->list[a].end <=
818 MAX_REGISTER_VIRTUAL_SIZE)
819 {
820 memranges->list[a].end = memranges->list[b].end;
821 continue; /* next b, same a */
822 }
823 a++; /* next a */
824 if (a != b)
825 memcpy (&memranges->list[a], &memranges->list[b],
826 sizeof (struct memrange));
827 }
828 memranges->next_memrange = a + 1;
829 }
830}
831
832void
833add_register (collection, regno)
834 struct collection_list *collection;
835 unsigned long regno;
836{
837 if (info_verbose)
838 printf_filtered ("collect register %d\n", regno);
839 if (regno > (8 * sizeof (collection->regs_mask)))
840 error ("Internal: register number %d too large for tracepoint",
841 regno);
842 collection->regs_mask [regno / 8] |= 1 << (regno % 8);
843}
844
845static void
846add_memrange (memranges, type, base, len)
847 struct collection_list *memranges;
848 int type;
849 bfd_signed_vma base;
850 unsigned long len;
851{
852 if (info_verbose)
853 printf_filtered ("(%d,0x%x,%d)\n", type, base, len);
854 /* type: 0 == memory, n == basereg */
855 memranges->list[memranges->next_memrange].type = type;
856 /* base: addr if memory, offset if reg relative. */
857 memranges->list[memranges->next_memrange].start = base;
858 /* len: we actually save end (base + len) for convenience */
859 memranges->list[memranges->next_memrange].end = base + len;
860 memranges->next_memrange++;
861 if (memranges->next_memrange >= memranges->listsize)
862 {
863 memranges->listsize *= 2;
864 memranges->list = xrealloc (memranges->list,
865 memranges->listsize);
866 }
867
868 if (type != 0) /* better collect the base register! */
869 add_register (memranges, type);
870}
871
872static void
873collect_symbol (collect, sym)
874 struct collection_list *collect;
875 struct symbol *sym;
876{
877 unsigned long len;
878 unsigned long reg;
879 bfd_signed_vma offset;
880
881 len = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
882 switch (SYMBOL_CLASS (sym)) {
883 default:
884 printf_filtered ("%s: don't know symbol class %d\n",
885 SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
886 break;
887 case LOC_CONST:
888 printf_filtered ("%s is constant, value is %d: will not be collected.\n",
889 SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
890 break;
891 case LOC_STATIC:
892 offset = SYMBOL_VALUE_ADDRESS (sym);
893 if (info_verbose)
894 printf_filtered ("LOC_STATIC %s: collect %d bytes "
895 "at 0x%08x\n",
896 SYMBOL_NAME (sym), len, offset);
897 add_memrange (collect, 0, offset, len); /* 0 == memory */
898 break;
899 case LOC_REGISTER:
900 case LOC_REGPARM:
901 reg = SYMBOL_VALUE (sym);
902 if (info_verbose)
903 printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
904 add_register (collect, reg);
905 break;
906 case LOC_ARG:
907 case LOC_REF_ARG:
908 printf_filtered ("Sorry, don't know how to do LOC_ARGs yet.\n");
909 printf_filtered (" (will not collect %s)\n",
910 SYMBOL_NAME (sym));
911 break;
912 case LOC_REGPARM_ADDR:
913 reg = SYMBOL_VALUE (sym);
914 offset = 0;
915 if (info_verbose)
916 {
917 printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset %d from reg %d\n",
918 SYMBOL_NAME (sym), len, offset, reg);
919 }
920 add_memrange (collect, reg, offset, len);
921 break;
922 case LOC_LOCAL:
923 case LOC_LOCAL_ARG:
924 offset = SYMBOL_VALUE (sym);
925 reg = FP_REGNUM;
926 if (info_verbose)
927 {
928 printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset %d from frame ptr reg %d\n",
929 SYMBOL_NAME (sym), len, offset, reg);
930 }
931 add_memrange (collect, reg, offset, len);
932 break;
933 case LOC_BASEREG:
934 case LOC_BASEREG_ARG:
935 reg = SYMBOL_BASEREG (sym);
936 offset = SYMBOL_VALUE (sym);
937 if (info_verbose)
938 {
939 printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n",
940 SYMBOL_NAME (sym), len, offset, reg);
941 }
942 add_memrange (collect, reg, offset, len);
943 break;
944 case LOC_UNRESOLVED:
945 printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
946 break;
947 case LOC_OPTIMIZED_OUT:
948 printf_filtered ("%s has been optimized out of existance.\n",
949 SYMBOL_NAME (sym));
950 break;
951 }
952}
953
954static void
955add_local_symbols (collect, pc, type)
956 struct collection_list *collect;
957 CORE_ADDR pc;
958 char type;
959{
960 struct symbol *sym;
961 struct block *block;
962 int i, nsyms, count = 0;
963
964 block = block_for_pc (pc);
965 while (block != 0)
966 {
967 nsyms = BLOCK_NSYMS (block);
968 for (i = 0; i < nsyms; i++)
969 {
970 sym = BLOCK_SYM (block, i);
971 switch (SYMBOL_CLASS (sym)) {
972 case LOC_LOCAL:
973 case LOC_STATIC:
974 case LOC_REGISTER:
975 case LOC_BASEREG:
976 if (type == 'L') /* collecting Locals */
977 {
978 count++;
979 collect_symbol (collect, sym);
980 }
981 break;
982 case LOC_ARG:
983 case LOC_LOCAL_ARG:
984 case LOC_REF_ARG:
985 case LOC_REGPARM:
986 case LOC_REGPARM_ADDR:
987 case LOC_BASEREG_ARG:
988 if (type == 'A') /* collecting Arguments */
989 {
990 count++;
991 collect_symbol (collect, sym);
992 }
993 }
994 }
995 if (BLOCK_FUNCTION (block))
996 break;
997 else
998 block = BLOCK_SUPERBLOCK (block);
999 }
1000 if (count == 0)
1001 warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
1002}
1003
1004static void
1005clear_collection_list (list)
1006 struct collection_list *list;
1007{
1008 list->next_memrange = 0;
1009 memset (list->regs_mask, 0, sizeof (list->regs_mask));
1010}
1011
1012static char *
1013stringify_collection_list (list, string)
1014 struct collection_list *list;
1015 char *string;
1016{
1017 char *end = string;
1018 long i;
1019
1020 for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1021 if (list->regs_mask[i] != 0) /* skip leading zeroes in regs_mask */
1022 break;
1023 if (list->regs_mask[i] != 0) /* prepare to send regs_mask to the stub */
1024 {
1025 if (info_verbose)
1026 printf_filtered ("\nCollecting registers (mask): 0x");
1027 *end++='R';
1028 for (; i >= 0; i--)
1029 {
1030 if (info_verbose)
1031 printf_filtered ("%02X", list->regs_mask[i]);
1032 sprintf (end, "%02X", list->regs_mask[i]);
1033 end += 2;
1034 }
1035 }
1036 if (info_verbose)
1037 printf_filtered ("\n");
1038 if (list->next_memrange > 0 && info_verbose)
1039 printf_filtered ("Collecting memranges: \n");
1040 for (i = 0; i < list->next_memrange; i++)
1041 {
1042 if (info_verbose)
1043 printf_filtered ("(%d, 0x%x, %d)\n",
1044 list->list[i].type,
1045 list->list[i].start,
1046 list->list[i].end - list->list[i].start);
1047 sprintf (end, "M%X,%X,%X",
1048 list->list[i].type,
1049 list->list[i].start,
1050 list->list[i].end - list->list[i].start);
1051 end += strlen (end);
1052 }
1053 if (end == string)
1054 return NULL;
1055 else
1056 return string;
1057}
1058
1059static void
1060encode_actions (t, tdp_actions, step_count, stepping_actions)
1061 struct tracepoint *t;
1062 char **tdp_actions;
1063 unsigned long *step_count;
1064 char **stepping_actions;
1065{
1066 struct expression *exp;
1067 static char tdp_buff[2048], step_buff[2048];
1068 struct action_line *action;
1069 char *action_exp;
1070 bfd_signed_vma offset;
1071 long i;
1072 struct collection_list *collect;
1073
1074 clear_collection_list (&tracepoint_list);
1075 clear_collection_list (&stepping_list);
1076 collect = &tracepoint_list;
1077
1078 *tdp_actions = NULL;
1079 *stepping_actions = NULL;
1080
1081 for (action = t->actions; action; action = action->next)
1082 {
1083 action_exp = action->action;
1084 while (isspace (*action_exp))
1085 action_exp++;
1086
1087 if (0 == strncasecmp (action_exp, "collect", 7))
1088 {
1089 action_exp = action_exp + 7;
1090 do { /* repeat over a comma-separated list */
1091 while (isspace (*action_exp))
1092 action_exp++;
1093
1094 if (0 == strncasecmp ("$reg", action_exp, 4))
1095 {
1096 for (i = 0; i < NUM_REGS; i++)
1097 add_register (collect, i);
1098 action_exp = (char *) strchr (action_exp, ','); /* more? */
1099 }
1100 else if (0 == strncasecmp ("$arg", action_exp, 4))
1101 {
1102 add_local_symbols (collect, t->address, 'A');
1103 action_exp = (char *) strchr (action_exp, ','); /* more? */
1104 }
1105 else if (0 == strncasecmp ("$loc", action_exp, 4))
1106 {
1107 add_local_symbols (collect, t->address, 'L');
1108 action_exp = (char *) strchr (action_exp, ','); /* more? */
1109 }
1110 else
1111 {
1112 unsigned long addr, len;
1113
1114 exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
1115 switch (exp->elts[0].opcode) {
1116 case OP_REGISTER:
1117 i = exp->elts[1].longconst;
1118 if (info_verbose)
1119 printf_filtered ("OP_REGISTER: ");
1120 add_register (collect, i);
1121 break;
1122 case OP_VAR_VALUE:
1123 collect_symbol (collect, exp->elts[2].symbol);
1124 break;
1125#if 0
1126 case OP_LONG:
1127 addr = exp->elts[2].longconst;
1128 if (*action_exp == ':')
1129 {
1130 exp = parse_exp_1 (&action_exp,
1131 block_for_pc (t->address),
1132 1);
1133 if (exp->elts[0].opcode == OP_LONG)
1134 len = exp->elts[2].longconst;
1135 else
1136 error ("length field requires a literal long const");
1137 }
1138 else
1139 len = 4;
1140
1141 add_memrange (collect, 0, addr, len);
1142 break;
1143#endif
1144 }
1145 }
1146 } while (action_exp && *action_exp++ == ',');
1147 }
1148 else if (0 == strncasecmp (action_exp, "while-stepping", 14))
1149 {
1150 collect = &stepping_list;
1151 }
1152 else if (0 == strncasecmp (action_exp, "end", 3))
1153 {
1154 if (collect == &stepping_list) /* end stepping actions */
1155 collect = &tracepoint_list;
1156 else
1157 break; /* end tracepoint actions */
1158 }
1159 }
1160 memrange_sortmerge (&tracepoint_list);
1161 memrange_sortmerge (&stepping_list);
1162
1163 *tdp_actions = stringify_collection_list (&tracepoint_list, &tdp_buff);
1164 *stepping_actions = stringify_collection_list (&stepping_list, &step_buff);
1165}
1166
1167static char target_buf[2048];
1168
1169static void
1170trace_start_command (args, from_tty)
1171 char *args;
1172 int from_tty;
1173{ /* STUB_COMM MOSTLY_IMPLEMENTED */
1174 struct tracepoint *t;
1175 char buf[2048];
1176 char *tdp_actions;
1177 char *stepping_actions;
1178 unsigned long step_count;
1179
1180 dont_repeat (); /* like "run", dangerous to repeat accidentally */
1181
1182 if (target_is_remote ())
1183 {
1184 putpkt ("QTinit");
1185 remote_get_noisy_reply (target_buf);
1186 if (strcmp (target_buf, "OK"))
1187 error ("Target does not support this command.");
1188
1189 ALL_TRACEPOINTS (t)
1190 {
1191 int ss_count; /* if actions include singlestepping */
1192 int disable_mask; /* ??? */
1193 int enable_mask; /* ??? */
1194
1195 sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address,
1196 t->enabled == enabled ? 'E' : 'D',
1197 t->step_count, t->pass_count);
1198 if (t->actions)
1199 {
1200 encode_actions (t, &tdp_actions, &step_count, &stepping_actions);
1201 /* do_single_steps (t); */
1202 if (tdp_actions)
1203 {
1204 if (strlen (buf) + strlen (tdp_actions) >= sizeof (buf))
1205 error ("Actions for tracepoint %d too complex; "
1206 "please simplify.", t->number);
1207 strcat (buf, tdp_actions);
1208 }
1209 if (stepping_actions)
1210 {
1211 strcat (buf, "S");
1212 if (strlen (buf) + strlen (stepping_actions) >= sizeof (buf))
1213 error ("Actions for tracepoint %d too complex; "
1214 "please simplify.", t->number);
1215 strcat (buf, stepping_actions);
1216 }
1217 }
1218 putpkt (buf);
1219 remote_get_noisy_reply (target_buf);
1220 if (strcmp (target_buf, "OK"))
1221 error ("Target does not support tracepoints.");
1222 }
1223 putpkt ("QTStart");
1224 remote_get_noisy_reply (target_buf);
1225 if (strcmp (target_buf, "OK"))
1226 error ("Bogus reply from target: %s", target_buf);
1227 }
1228 else
1229 printf_filtered ("Trace can only be run on remote targets.\n");
1230}
1231
1232static void
1233trace_stop_command (args, from_tty)
1234 char *args;
1235 int from_tty;
1236{ /* STUB_COMM IS_IMPLEMENTED */
1237 if (target_is_remote ())
1238 {
1239 putpkt ("QTStop");
1240 remote_get_noisy_reply (target_buf);
1241 if (strcmp (target_buf, "OK"))
1242 error ("Bogus reply from target: %s", target_buf);
1243 }
1244 else
1245 error ("Trace can only be run on remote targets.");
1246}
1247
1248static void
1249trace_status_command (args, from_tty)
1250 char *args;
1251 int from_tty;
1252{ /* STUB_COMM IS_IMPLEMENTED */
1253 if (target_is_remote ())
1254 {
1255 putpkt ("qTStatus");
1256 remote_get_noisy_reply (target_buf);
1257 if (strcmp (target_buf, "OK"))
1258 error ("Bogus reply from target: %s", target_buf);
1259 }
1260 else
1261 error ("Trace can only be run on remote targets.");
1262}
1263
1264static void
1265trace_buff_command (args, from_tty)
1266 char *args;
1267 int from_tty;
1268{ /* STUB_COMM NOT_IMPLEMENTED */
1269 if (args == 0 || *args == 0)
1270 printf_filtered ("TBUFFER command requires argument (on or off)\n");
1271 else if (strcasecmp (args, "on") == 0)
1272 printf_filtered ("tbuffer overflow on.\n");
1273 else if (strcasecmp (args, "off") == 0)
1274 printf_filtered ("tbuffer overflow off.\n");
1275 else
1276 printf_filtered ("TBUFFER: unknown argument (use on or off)\n");
1277}
1278
1279static void
1280trace_limit_command (args, from_tty)
1281 char *args;
1282 int from_tty;
1283{ /* STUB_COMM NOT_IMPLEMENTED */
1284 printf_filtered ("Limit it to what?\n");
1285}
1286
1287static void
1288trace_find_command (args, from_tty)
1289 char *args;
1290 int from_tty;
1291{ /* STUB_COMM PART_IMPLEMENTED */
1292 /* this should only be called with a numeric argument */
1293 int frameno, target_frameno;
1294 char buf[40], *tmp;
1295
1296 if (target_is_remote ())
1297 {
1298 if (args == 0 || *args == 0)
1299 frameno = traceframe_number + 1;
1300 else if (*args != '-' && !isdigit(*args))
1301 error ("tfind requires a literal (for now): %s rejected.", args);
1302 else
1303 frameno = strtol (args, 0, 0); /* for now, literals only */
1304
1305 sprintf (buf, "QTFrame:%x", frameno);
1306 putpkt (buf);
1307 remote_get_noisy_reply (target_buf);
1308
1309 if (target_buf[0] != 'F')
1310 error ("Bogus reply from target: %s", target_buf);
1311 target_frameno = strtol (&target_buf[1], &tmp, 16);
1312 if (tmp == &target_buf[1])
1313 error ("Bogus reply from target: %s", target_buf);
1314 if (target_frameno != frameno)
1315 warning ("Target replied with different framenumber, %s != %x",
1316 target_buf, frameno);
1317
1318 set_traceframe_num (target_frameno);
1319 flush_cached_frames ();
1320 registers_changed ();
1321 select_frame (get_current_frame (), 0);
1322 }
1323 else
1324 error ("Trace can only be run on remote targets.");
1325}
1326
1327static void
1328trace_find_pc_command (args, from_tty)
1329 char *args;
1330 int from_tty;
1331{ /* STUB_COMM PART_IMPLEMENTED */
1332 CORE_ADDR pc;
1333 int target_frameno;
1334 char buf[40], *tmp;
1335
1336 if (target_is_remote ())
1337 {
1338 if (args == 0 || *args == 0)
1339 { /* TFIND PC <no args> is the same as TFIND <no args> */
1340 trace_find_command (args, from_tty);
1341 return;
1342 }
1343 if (!isdigit(*args))
1344 error ("tfind pc requires a literal argument (for now): %s rejected.",
1345 args);
1346
1347 pc = strtol (args, 0, 0); /* for now, literals only */
1348 sprintf (buf, "QTFrame:pc:%x", pc);
1349 putpkt (buf);
1350 remote_get_noisy_reply (target_buf);
1351
1352 if (target_buf[0] != 'F')
1353 error ("Bogus reply from target: %s", target_buf);
1354 target_frameno = strtol (&target_buf[1], &tmp, 16);
1355 if (tmp == &target_buf[1])
1356 error ("Bogus reply from target: %s", target_buf);
1357
1358 set_traceframe_num (target_frameno);
1359 flush_cached_frames ();
1360 registers_changed ();
1361 select_frame (get_current_frame (), 0);
1362 }
1363 else
1364 error ("Trace can only be run on remote targets.");
1365}
1366
1367static void
1368trace_find_tdp_command (args, from_tty)
1369 char *args;
1370 int from_tty;
1371{ /* STUB_COMM PART_IMPLEMENTED */
1372 int target_frameno, tdp;
1373 char buf[40], *tmp;
1374
1375 if (target_is_remote ())
1376 {
1377 if (args == 0 || *args == 0)
1378 { /* TFIND TDP <no args> is the same as TFIND <no args> */
1379 trace_find_command (args, from_tty);
1380 return;
1381 }
1382 if (!isdigit(*args))
1383 error ("tfind tdp command requires a literal argument (for now): %s",
1384 args);
1385
1386 tdp = strtol (args, 0, 0); /* for now, literals only */
1387 sprintf (buf, "QTFrame:tdp:%x", tdp);
1388 putpkt (buf);
1389 remote_get_noisy_reply (target_buf);
1390
1391 if (target_buf[0] != 'F')
1392 error ("Bogus reply from target: %s", target_buf);
1393 target_frameno = strtol (&target_buf[1], &tmp, 16);
1394 if (tmp == &target_buf[1])
1395 error ("Bogus reply from target: %s", target_buf);
1396
1397 set_traceframe_num (target_frameno);
1398 flush_cached_frames ();
1399 registers_changed ();
1400 select_frame (get_current_frame (), 0);
1401 }
1402 else
1403 error ("Trace can only be run on remote targets.");
1404}
1405
1406static void
1407trace_find_range_command (args, from_tty)
1408 char *args;
1409 int from_tty;
1410{ /* STUB_COMM PART_IMPLEMENTED */
1411 static CORE_ADDR start, stop;
1412 int target_frameno;
1413 char buf[50], *tmp;
1414
1415 if (target_is_remote ())
1416 {
1417 if (args == 0 || *args == 0 || !isdigit(*args))
1418 { /* XXX FIXME: what should default behavior be? */
1419 printf_filtered ("Usage: tfind range <address> <address>\n");
1420 return;
1421 }
1422
1423 start = strtol (args, &args, 0); /* for now, literals only */
1424 while (args && *args && isspace (*args))
1425 args++;
1426
1427 if (args == 0 || *args == 0 || !isdigit(*args))
1428 {
1429 printf_filtered ("Usage: tfind range <address> <address>\n");
1430 return;
1431 }
1432
1433 stop = strtol (args, &args, 0); /* for now, literals only */
1434
1435 sprintf (buf, "QTFrame:range:%x:%x", start, stop);
1436 putpkt (buf);
1437 remote_get_noisy_reply (target_buf);
1438
1439 if (target_buf[0] != 'F')
1440 error ("Bogus reply from target: %s", target_buf);
1441 target_frameno = strtol (&target_buf[1], &tmp, 16);
1442 if (tmp == &target_buf[1])
1443 error ("Bogus reply from target: %s", target_buf);
1444
1445 set_traceframe_num (target_frameno);
1446 flush_cached_frames ();
1447 registers_changed ();
1448 select_frame (get_current_frame (), 0);
1449 }
1450 else
1451 error ("Trace can only be run on remote targets.");
1452}
1453
1454static void
1455trace_find_outside_command (args, from_tty)
1456 char *args;
1457 int from_tty;
1458{ /* STUB_COMM PART_IMPLEMENTED */
1459 CORE_ADDR start, stop;
1460 int target_frameno;
1461 char buf[50], *tmp;
1462
1463 if (target_is_remote ())
1464 {
1465 if (args == 0 || *args == 0 || !isdigit(*args))
1466 { /* XXX FIXME: what should default behavior be? */
1467 printf_filtered ("Usage: tfind outside <address> <address>\n");
1468 return;
1469 }
1470
1471 start = strtol (args, &args, 0);
1472 while (args && *args && isspace (*args))
1473 args++;
1474
1475 if (args == 0 || *args == 0 || !isdigit(*args))
1476 {
1477 printf_filtered ("Usage: tfind outside <address> <address>\n");
1478 return;
1479 }
1480
1481 stop = strtol (args, &args, 0);
1482
1483 sprintf (buf, "QTFrame:outside:%x:%x", start, stop);
1484 putpkt (buf);
1485 remote_get_noisy_reply (target_buf);
1486
1487 if (target_buf[0] != 'F')
1488 error ("Bogus reply from target: %s", target_buf);
1489 target_frameno = strtol (&target_buf[1], &tmp, 16);
1490 if (tmp == &target_buf[1])
1491 error ("Bogus reply from target: %s", target_buf);
1492
1493 set_traceframe_num (target_frameno);
1494 flush_cached_frames ();
1495 registers_changed ();
1496 select_frame (get_current_frame (), 0);
1497 }
1498 else
1499 error ("Trace can only be run on remote targets.");
1500}
1501
1502static void
1503trace_display_command (args, from_tty)
1504 char *args;
1505 int from_tty;
1506{ /* STUB_COMM NOT_IMPLEMENTED */
1507 if (!target_is_remote ())
1508 {
1509 printf_filtered ("Trace can only be run on remote targets.\n");
1510 return;
1511 }
1512
1513 if (args && *args)
1514 printf_filtered ("Displaying trace as %s.\n", args);
1515 else
1516 printf_filtered ("Displaying trace.\n");
1517}
1518
1519static void
1520tracepoint_save_command (args, from_tty)
1521 char *args;
1522 int from_tty;
1523{
1524 struct tracepoint *tp;
1525 struct action_line *line;
1526 FILE *fp;
1527 char *i1 = " ", *i2 = " ";
1528 char *indent, *actionline;
1529
1530 if (args == 0 || *args == 0)
1531 error ("Argument required (file name in which to save tracepoints");
1532
1533 if (tracepoint_chain == 0)
1534 {
1535 warning ("save-tracepoints: no tracepoints to save.\n");
1536 return;
1537 }
1538
1539 if (!(fp = fopen (args, "w")))
1540 error ("Unable to open file '%s' for saving tracepoints");
1541
1542 ALL_TRACEPOINTS (tp)
1543 {
1544 if (tp->addr_string)
1545 fprintf (fp, "trace %s\n", tp->addr_string);
1546 else
1547 fprintf (fp, "trace *0x%x\n", tp->address);
1548
1549 if (tp->pass_count)
1550 fprintf (fp, " passcount %d\n", tp->pass_count);
1551
1552 if (tp->actions)
1553 {
1554 fprintf (fp, " actions\n");
1555 indent = i1;
1556 for (line = tp->actions; line; line = line->next)
1557 {
1558 actionline = line->action;
1559 while (isspace(*actionline))
1560 actionline++;
1561
1562 fprintf (fp, "%s%s\n", indent, actionline);
1563 if (0 == strncasecmp (actionline, "while-stepping", 14))
1564 indent = i2;
1565 else if (0 == strncasecmp (actionline, "end", 3))
1566 indent = i1;
1567 }
1568 }
1569 }
1570 fclose (fp);
1571 if (from_tty)
1572 printf_filtered ("Tracepoints saved to file '%s'.\n", args);
1573 return;
1574}
1575
1576static void
1577scope_info (args, from_tty)
1578 char *args;
1579 int from_tty;
1580{
1581 struct symtab_and_line sal;
1582 struct symtabs_and_lines sals;
1583 struct symbol *sym;
1584 struct block *block;
1585 char **canonical, *save_args = args, *symname;
1586 int i, nsyms, count = 0;
1587 enum address_class aclass;
1588
1589 if (args == 0 || *args == 0)
1590 error ("requires an argument (function, line or *addr) to define a scope");
1591
1592 sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
1593 if (sals.nelts == 0)
1594 return; /* presumably decode_line_1 has already warned */
1595
1596 printf_filtered ("Block for %s", save_args);
1597 /* Resolve all line numbers to PC's */
1598 for (i = 0; i < sals.nelts; i++)
1599 resolve_sal_pc (&sals.sals[i]);
1600
1601 block = block_for_pc (sals.sals[0].pc);
1602 while (block != 0)
1603 {
1604 nsyms = BLOCK_NSYMS (block);
1605 for (i = 0; i < nsyms; i++)
1606 {
1607 count++;
1608 sym = BLOCK_SYM (block, i);
1609 switch (SYMBOL_CLASS (sym)) {
1610 default:
1611 case LOC_UNDEF: /* messed up symbol? */
1612 symname = SYMBOL_NAME (sym);
1613 if (symname && *symname) /* guard against messed up name */
1614 printf_filtered ("Bogus symbol %s, class %d\n",
1615 symname, SYMBOL_CLASS (sym));
1616 else
1617 printf_filtered ("Completely bogus symbol, class %d.\n",
1618 SYMBOL_CLASS (sym));
1619 count--; /* don't count this one */
1620 continue;
1621 case LOC_CONST: printf_filtered ("\nConstant "); break;
1622 case LOC_STATIC: printf_filtered ("\nStatic "); break;
1623 case LOC_REGISTER: printf_filtered ("\nRegister "); break;
1624 case LOC_ARG: printf_filtered ("\nArg "); break;
1625 case LOC_REF_ARG: printf_filtered ("\nReference Arg "); break;
1626 case LOC_REGPARM: printf_filtered ("\nRegister Arg "); break;
1627 case LOC_REGPARM_ADDR:
1628 printf_filtered ("\nIndirect Register Arg "); break;
1629 case LOC_LOCAL: printf_filtered ("\nStack Local "); break;
1630 case LOC_TYPEDEF: printf_filtered ("\nLocal Typedef "); break;
1631 case LOC_LABEL: printf_filtered ("\nLocal Label "); break;
1632 case LOC_BLOCK: printf_filtered ("\nLocal Function "); break;
1633 case LOC_CONST_BYTES: printf_filtered ("\nLoc. Byte Seq. "); break;
1634 case LOC_LOCAL_ARG: printf_filtered ("\nStack Arg "); break;
1635 case LOC_BASEREG: printf_filtered ("\nBasereg Local "); break;
1636 case LOC_BASEREG_ARG: printf_filtered ("\nBasereg Arg "); break;
1637 case LOC_UNRESOLVED:
1638 printf_filtered ("\nUnresolved Static "); break;
1639 case LOC_OPTIMIZED_OUT: printf_filtered ("\nOptimized-Out "); break;
1640 }
1641 type_print (SYMBOL_TYPE (sym), SYMBOL_NAME (sym), gdb_stdout, -1);
1642 }
1643 if (BLOCK_FUNCTION (block))
1644 break;
1645 else
1646 block = BLOCK_SUPERBLOCK (block);
1647 }
1648 if (count <= 0)
1649 printf_filtered (" contains no locals or arguments.");
1650 printf_filtered ("\n");
1651}
1652
1653static struct cmd_list_element *tfindlist;
1654static struct cmd_list_element *tracelist;
1655
1656void
1657_initialize_tracepoint ()
1658{
1659 tracepoint_chain = 0;
1660 tracepoint_count = 0;
1661 traceframe_number = 0;
1662
1663 set_internalvar (lookup_internalvar ("tpnum"),
1664 value_from_longest (builtin_type_int, (LONGEST) 0));
1665 set_internalvar (lookup_internalvar ("trace_frame"),
1666 value_from_longest (builtin_type_int, (LONGEST) 0));
1667
1668 if (tracepoint_list.list == NULL)
1669 {
1670 tracepoint_list.listsize = 128;
1671 tracepoint_list.list = xmalloc
1672 (tracepoint_list.listsize * sizeof (struct memrange));
1673 }
1674 if (stepping_list.list == NULL)
1675 {
1676 stepping_list.listsize = 128;
1677 stepping_list.list = xmalloc
1678 (stepping_list.listsize * sizeof (struct memrange));
1679 }
1680
1681 add_info ("scope", scope_info,
1682 "List the variables local to a scope");
1683
1684#if 1
1685 add_cmd ("tracepoints", class_trace, NO_FUNCTION,
1686 "Tracing program execution without stopping the program.",
1687 &cmdlist);
1688
1689 add_info ("tracepoints", tracepoints_info,
1690 "Display tracepoints, or tracepoint number NUMBER.\n"
1691 "Convenience variable \"$tpnum\" contains the number of the\n"
1692 "last tracepoint set.");
1693
1694 add_info_alias ("tp", "tracepoints", 1);
1695
1696 add_com ("save-tracepoints", class_trace, tracepoint_save_command,
1697 "Save current tracepoint definitions as a script.\n"
1698 "Use the SOURCE command in another debug session to restore them.");
1699
1700 add_com ("tlimit", class_trace, trace_limit_command,
1701 "Not sure what this should do yet....");
1702
1703 add_com ("tbuffer", class_trace, trace_buff_command,
1704 "See also 'set trace buffer overflow'.");
1705
1706 add_prefix_cmd ("tfind", class_trace,
1707 trace_find_command,
1708 "Select a trace frame (default by frame number).",
1709 &tfindlist, "tfind ", 1, &cmdlist);
1710
1711 add_cmd ("outside", class_trace, trace_find_outside_command,
1712 "Select a trace frame by falling outside of a PC range",
1713 &tfindlist);
1714
1715 add_cmd ("range", class_trace, trace_find_range_command,
1716 "Select a trace frame by PC range", &tfindlist);
1717
1718 add_cmd ("tdp", class_trace, trace_find_tdp_command,
1719 "Select a trace frame by TDP", &tfindlist);
1720
1721 add_cmd ("pc", class_trace, trace_find_pc_command,
1722 "Select a trace frame by PC", &tfindlist);
1723
1724 add_com ("tdisplay", class_trace, trace_display_command,
1725 "Display the results of a trace");
1726
1727 add_com ("tstatus", class_trace, trace_status_command,
1728 "Inquire about trace data collection status.");
1729
1730 add_com ("tstop", class_trace, trace_stop_command,
1731 "Stop trace data collection.");
1732
1733 add_com ("tstart", class_trace, trace_start_command,
1734 "Start trace data collection.");
1735
1736 add_com ("passcount", class_trace, trace_pass_command,
1737 "Set the passcount for a tracepoint.\n"
1738 "The trace will end when the tracepoint has been passed "
1739 "'count' times.\n"
1740 "Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\",\n"
1741 "or if omitted refers to the last tracepoint defined.");
1742
1743 add_com ("actions", class_trace, trace_actions_command,
1744 "Specify the actions to be taken at a tracepoint.\n"
1745 "Actions can include collection of data, enabling or \n"
1746 "disabling other tracepoints, or ending the trace.");
1747
1748 add_cmd ("tracepoints", class_trace, delete_trace_command,
1749 "Delete specified tracepoints; or with no argument, delete all.",
1750 &deletelist);
1751
1752 add_cmd ("tracepoints", class_trace, disable_trace_command,
1753 "Disable specified tracepoints; or with no argument, disable all.",
1754 &disablelist);
1755
1756 add_cmd ("tracepoints", class_trace, enable_trace_command,
1757 "Enable specified tracepoints; or with no argument, enable all.",
1758 &enablelist);
1759
1760 add_com ("trace", class_trace, trace_command,
1761 "Set a tracepoint at a specified line, function, or address.\n"
1762 "Argument may be a line number, function name, or "
1763 "'*' plus an address.\n"
1764 "For a line number or function, trace at the start of its code.\n"
1765 "If an address is specified, trace at that exact address.");
1766
1767 add_com_alias ("tp", "trace", class_alias, 0);
1768 add_com_alias ("tr", "trace", class_alias, 1);
1769 add_com_alias ("tra", "trace", class_alias, 1);
1770 add_com_alias ("trac", "trace", class_alias, 1);
1771
1772
1773#else /* command set based on TRACE as a prefix (incomplete) */
1774 add_cmd ("tracepoints", class_trace, NO_FUNCTION,
1775 "Tracing program execution without stopping the program.",
1776 &cmdlist);
1777
1778 add_prefix_cmd ("trace", class_trace, trace_command,
1779 "prefix for tracing commands",
1780 &tracelist, "trace ", 1, &cmdlist);
1781
1782 add_cmd ("limit", class_trace, trace_limit_command,
1783 "Not sure what the hell this does....", &tracelist);
1784
1785 add_cmd ("buffer", class_trace, trace_buff_command,
1786 "See also 'set trace buffer overflow'.", &tracelist);
1787
1788 add_prefix_cmd ("find", class_trace, trace_find_command,
1789 "Select a trace frame (default by frame number).",
1790 &tfindlist, "trace find ", 1, &tracelist);
1791
1792 add_cmd ("outside", class_trace, trace_find_outside_command,
1793 "Select a tracepoint by falling outside of a PC range.",
1794 &tfindlist);
1795
1796 add_cmd ("range", class_trace, trace_find_range_command,
1797 "Select a tracepoint by PC range.",
1798 &tfindlist);
1799
1800 add_cmd ("pc", class_trace, trace_find_pc_command,
1801 "Select a tracepoint by PC.",
1802 &tfindlist);
1803
1804 add_cmd ("display", class_trace, trace_display_command,
1805 "Display the results of a trace.", &tracelist);
1806
1807 add_cmd ("delete", class_trace, delete_trace_command,
1808 "Delete some tracepoints; no argument means all.", &tracelist);
1809
1810 add_cmd ("disable", class_trace, disable_trace_command,
1811 "Disable some tracepoints; no argument means all.", &tracelist);
1812
1813 add_cmd ("enable", class_trace, enable_trace_command,
1814 "Enable some tracepoints; no argument means all.", &tracelist);
1815
1816 add_cmd ("tracepoints", class_trace, delete_trace_command,
1817 "Delete some tracepoints; no argument means all.",
1818 &deletelist);
1819
1820 add_cmd ("tracepoints", class_trace, disable_trace_command,
1821 "Disable some tracepoints; no argument means all.",
1822 &disablelist);
1823
1824 add_cmd ("tracepoints", class_trace, enable_trace_command,
1825 "Enable some tracepoints; no argument means all.",
1826 &enablelist);
1827
1828 add_cmd ("at", class_trace, trace_command,
1829 "Set a tracepoint at a specified line or function.\n"
1830 "Argument may be a line number, function name, or "
1831 "'*' and an address.\n"
1832 "For a line number or function, trace from the start of "
1833 "its code.\n"
1834 "If an address is specified, trace at that exact address.\n"
1835 "With no arg, uses current execution address of "
1836 "selected stack frame.\n"
1837 "This is useful for breaking on return to a stack frame.",
1838 &tracelist);
1839
1840 add_cmd ("status", class_trace, trace_status_command,
1841 "Inquire about trace data collection status.", &tracelist);
1842
1843 add_cmd ("stop", class_trace, trace_stop_command,
1844 "Stop trace data collection.", &tracelist);
1845
1846 add_cmd ("start", class_trace, trace_start_command,
1847 "Start trace data collection.", &tracelist);
1848
1849 add_cmd ("info", class_info, tracepoints_info,
1850 "Status of tracepoints, or tracepoint number NUMBER.\n"
1851 "The \"Address\" and \"What\" columns indicate the\n"
1852 "address and file/line number respectively.\n\n"
1853 "Convenience variable \"$tpnum\" contains the number of the\n"
1854 "last tracepoint set.",
1855 &tracelist);
1856
1857 add_info ("tracepoints", tracepoints_info,
1858 "Status of tracepoints, or tracepoint number NUMBER.\n"
1859 "The \"Address\" and \"What\" columns indicate the\n"
1860 "address and file/line number respectively.\n\n"
1861 "Convenience variable \"$tpnum\" contains the number of the\n"
1862 "last tracepoint set.");
1863
1864 add_info_alias ("tp", "tracepoints", 1);
1865
1866#endif
1867}