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