import gdb-1999-06-14 snapshot
[platform/upstream/binutils.git] / gdb / tracepoint.c
1 /* Tracing functionality for remote targets in custom GDB protocol
2    Copyright 1997, 1998 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #include "defs.h"
21 #include "symtab.h"
22 #include "frame.h"
23 #include "tracepoint.h"
24 #include "gdbtypes.h"
25 #include "expression.h"
26 #include "gdbcmd.h"
27 #include "value.h"
28 #include "target.h"
29 #include "language.h"
30 #include "gdb_string.h"
31
32 #include "ax.h"
33 #include "ax-gdb.h"
34
35 /* readline include files */
36 #include <readline/readline.h>
37 #include <readline/history.h>
38
39 /* readline defines this.  */
40 #undef savestring
41
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45
46 /* maximum length of an agent aexpression.
47    this accounts for the fact that packets are limited to 400 bytes
48    (which includes everything -- including the checksum), and assumes
49    the worst case of maximum length for each of the pieces of a
50    continuation packet.
51    
52    NOTE: expressions get mem2hex'ed otherwise this would be twice as
53    large.  (400 - 31)/2 == 184 */
54 #define MAX_AGENT_EXPR_LEN      184
55
56
57 extern int info_verbose;
58 extern void (*readline_begin_hook) PARAMS ((char *, ...));
59 extern char * (*readline_hook) PARAMS ((char *));
60 extern void (*readline_end_hook) PARAMS ((void));
61 extern void x_command PARAMS ((char *, int));
62 extern int addressprint;                /* Print machine addresses? */
63
64 /* If this definition isn't overridden by the header files, assume
65    that isatty and fileno exist on this system.  */
66 #ifndef ISATTY
67 #define ISATTY(FP)      (isatty (fileno (FP)))
68 #endif
69
70 /* 
71    Tracepoint.c:
72
73    This module defines the following debugger commands:
74    trace            : set a tracepoint on a function, line, or address.
75    info trace       : list all debugger-defined tracepoints.
76    delete trace     : delete one or more tracepoints.
77    enable trace     : enable one or more tracepoints.
78    disable trace    : disable one or more tracepoints.
79    actions          : specify actions to be taken at a tracepoint.
80    passcount        : specify a pass count for a tracepoint.
81    tstart           : start a trace experiment.
82    tstop            : stop a trace experiment.
83    tstatus          : query the status of a trace experiment.
84    tfind            : find a trace frame in the trace buffer.
85    tdump            : print everything collected at the current tracepoint.
86    save-tracepoints : write tracepoint setup into a file.
87
88    This module defines the following user-visible debugger variables:
89    $trace_frame : sequence number of trace frame currently being debugged.
90    $trace_line  : source line of trace frame currently being debugged.
91    $trace_file  : source file of trace frame currently being debugged.
92    $tracepoint  : tracepoint number of trace frame currently being debugged.
93    */
94
95
96 /* ======= Important global variables: ======= */
97
98 /* Chain of all tracepoints defined.  */
99 struct tracepoint *tracepoint_chain;
100
101 /* Number of last tracepoint made.  */
102 static int tracepoint_count;
103
104 /* Number of last traceframe collected.  */
105 static int traceframe_number;
106
107 /* Tracepoint for last traceframe collected.  */
108 static int tracepoint_number;
109
110 /* Symbol for function for last traceframe collected */
111 static struct symbol *traceframe_fun;
112
113 /* Symtab and line for last traceframe collected */
114 static struct symtab_and_line traceframe_sal;
115
116 /* Tracing command lists */
117 static struct cmd_list_element *tfindlist;
118
119 /* ======= Important command functions: ======= */
120 static void trace_command                 PARAMS ((char *, int));
121 static void tracepoints_info              PARAMS ((char *, int));
122 static void delete_trace_command          PARAMS ((char *, int));
123 static void enable_trace_command          PARAMS ((char *, int));
124 static void disable_trace_command         PARAMS ((char *, int));
125 static void trace_pass_command            PARAMS ((char *, int));
126 static void trace_actions_command         PARAMS ((char *, int));
127 static void trace_start_command           PARAMS ((char *, int));
128 static void trace_stop_command            PARAMS ((char *, int));
129 static void trace_status_command          PARAMS ((char *, int));
130 static void trace_find_command            PARAMS ((char *, int));
131 static void trace_find_pc_command         PARAMS ((char *, int));
132 static void trace_find_tracepoint_command PARAMS ((char *, int));
133 static void trace_find_line_command       PARAMS ((char *, int));
134 static void trace_find_range_command      PARAMS ((char *, int));
135 static void trace_find_outside_command    PARAMS ((char *, int));
136 static void tracepoint_save_command       PARAMS ((char *, int));
137 static void trace_dump_command            PARAMS ((char *, int));
138
139 /* support routines */
140 static void trace_mention                 PARAMS ((struct tracepoint *));
141
142 #if __STDC__
143 struct collection_list;
144 #endif
145 static void add_aexpr PARAMS ((struct collection_list *, struct agent_expr *));
146 static unsigned char *mem2hex(unsigned char *, unsigned char *, int);
147 static void add_register PARAMS ((struct collection_list *collection, unsigned long regno));
148 static void free_actions_list PARAMS ((char **actions_list));
149 static void free_actions_list_cleanup_wrapper PARAMS ((void*));
150
151 extern void _initialize_tracepoint PARAMS ((void));
152
153 /* Utility: returns true if "target remote" */
154 static int
155 target_is_remote ()
156 {
157   if (current_target.to_shortname &&
158       strcmp (current_target.to_shortname, "remote") == 0)
159     return 1;
160   else
161     return 0;
162 }
163
164 /* Utility: generate error from an incoming stub packet.  */
165 static void 
166 trace_error (buf)
167      char *buf;
168 {
169   if (*buf++ != 'E')
170     return;                     /* not an error msg */
171   switch (*buf) 
172     {
173     case '1':                   /* malformed packet error */
174       if (*++buf == '0')        /*   general case: */
175         error ("tracepoint.c: error in outgoing packet.");
176       else
177         error ("tracepoint.c: error in outgoing packet at field #%d.", 
178                strtol (buf, NULL, 16));
179     case '2':
180       error ("trace API error 0x%s.", ++buf);
181     default:
182       error ("Target returns error code '%s'.", buf);
183     }
184 }
185
186 /* Utility: wait for reply from stub, while accepting "O" packets */
187 static char *
188 remote_get_noisy_reply (buf)
189      char *buf;
190 {
191   do    /* loop on reply from remote stub */
192     {
193       QUIT;                             /* allow user to bail out with ^C */
194       getpkt (buf, 0);
195       if (buf[0] == 0)
196         error ("Target does not support this command.");
197       else if (buf[0] == 'E')
198         trace_error (buf);
199       else if (buf[0] == 'O' &&
200                buf[1] != 'K')
201         remote_console_output (buf + 1);        /* 'O' message from stub */
202       else
203         return buf;                             /* here's the actual reply */
204     } while (1);
205 }
206
207 /* Set tracepoint count to NUM.  */
208 static void
209 set_tracepoint_count (num)
210      int num;
211 {
212   tracepoint_count = num;
213   set_internalvar (lookup_internalvar ("tpnum"),
214                    value_from_longest (builtin_type_int, (LONGEST) num));
215 }
216
217 /* Set traceframe number to NUM.  */
218 static void
219 set_traceframe_num (num)
220      int num;
221 {
222   traceframe_number = num;
223   set_internalvar (lookup_internalvar ("trace_frame"),
224                    value_from_longest (builtin_type_int, (LONGEST) num));
225 }
226
227 /* Set tracepoint number to NUM.  */
228 static void
229 set_tracepoint_num (num)
230      int num;
231 {
232   tracepoint_number = num;
233   set_internalvar (lookup_internalvar ("tracepoint"),
234                    value_from_longest (builtin_type_int, (LONGEST) num));
235 }
236
237 /* Set externally visible debug variables for querying/printing
238    the traceframe context (line, function, file) */
239
240 static void
241 set_traceframe_context (trace_pc)
242      CORE_ADDR trace_pc;
243 {
244   static struct type *func_string, *file_string;
245   static struct type *func_range,  *file_range;
246   static value_ptr    func_val,     file_val;
247   static struct type *charstar;
248   int len;
249
250   if (charstar == (struct type *) NULL)
251     charstar = lookup_pointer_type (builtin_type_char);
252
253   if (trace_pc == -1)   /* cease debugging any trace buffers */
254     {
255       traceframe_fun = 0;
256       traceframe_sal.pc = traceframe_sal.line = 0;
257       traceframe_sal.symtab = NULL;
258       set_internalvar (lookup_internalvar ("trace_func"), 
259                        value_from_longest (charstar, (LONGEST) 0));
260       set_internalvar (lookup_internalvar ("trace_file"), 
261                        value_from_longest (charstar, (LONGEST) 0));
262       set_internalvar (lookup_internalvar ("trace_line"),
263                        value_from_longest (builtin_type_int, (LONGEST) -1));
264       return;
265     }
266
267   /* save as globals for internal use */
268   traceframe_sal = find_pc_line (trace_pc, 0);
269   traceframe_fun = find_pc_function (trace_pc);
270
271   /* save linenumber as "$trace_line", a debugger variable visible to users */
272   set_internalvar (lookup_internalvar ("trace_line"),
273                    value_from_longest (builtin_type_int, 
274                                        (LONGEST) traceframe_sal.line));
275
276   /* save func name as "$trace_func", a debugger variable visible to users */
277   if (traceframe_fun == NULL || 
278       SYMBOL_NAME (traceframe_fun) == NULL)
279     set_internalvar (lookup_internalvar ("trace_func"), 
280                      value_from_longest (charstar, (LONGEST) 0));
281   else
282     {
283       len = strlen (SYMBOL_NAME (traceframe_fun));
284       func_range  = create_range_type (func_range,  
285                                        builtin_type_int, 0, len - 1);
286       func_string = create_array_type (func_string, 
287                                        builtin_type_char, func_range);
288       func_val = allocate_value (func_string);
289       VALUE_TYPE (func_val) = func_string;
290       memcpy (VALUE_CONTENTS_RAW (func_val), 
291               SYMBOL_NAME (traceframe_fun), 
292               len);
293       func_val->modifiable = 0;
294       set_internalvar (lookup_internalvar ("trace_func"), func_val);
295     }
296
297   /* save file name as "$trace_file", a debugger variable visible to users */
298   if (traceframe_sal.symtab == NULL || 
299       traceframe_sal.symtab->filename == NULL)
300     set_internalvar (lookup_internalvar ("trace_file"), 
301                      value_from_longest (charstar, (LONGEST) 0));
302   else
303     {
304       len = strlen (traceframe_sal.symtab->filename);
305       file_range  = create_range_type (file_range,  
306                                        builtin_type_int, 0, len - 1);
307       file_string = create_array_type (file_string, 
308                                        builtin_type_char, file_range);
309       file_val = allocate_value (file_string);
310       VALUE_TYPE (file_val) = file_string;
311       memcpy (VALUE_CONTENTS_RAW (file_val), 
312               traceframe_sal.symtab->filename, 
313               len);
314       file_val->modifiable = 0;
315       set_internalvar (lookup_internalvar ("trace_file"), file_val);
316     }
317 }
318
319 /* Low level routine to set a tracepoint.
320    Returns the tracepoint object so caller can set other things.
321    Does not set the tracepoint number!
322    Does not print anything.
323
324    ==> This routine should not be called if there is a chance of later
325    error(); otherwise it leaves a bogus tracepoint on the chain.  Validate
326    your arguments BEFORE calling this routine!  */
327
328 static struct tracepoint *
329 set_raw_tracepoint (sal)
330      struct symtab_and_line sal;
331 {
332   register struct tracepoint *t, *tc;
333   struct cleanup *old_chain;
334
335   t = (struct tracepoint *) xmalloc (sizeof (struct tracepoint));
336   old_chain = make_cleanup (free, t);
337   memset (t, 0, sizeof (*t));
338   t->address = sal.pc;
339   if (sal.symtab == NULL)
340     t->source_file = NULL;
341   else
342     t->source_file = savestring (sal.symtab->filename, 
343                                  strlen (sal.symtab->filename));
344
345   t->section     = sal.section;
346   t->language    = current_language->la_language;
347   t->input_radix = input_radix;
348   t->line_number = sal.line;
349   t->enabled     = enabled;
350   t->next        = 0;
351   t->step_count  = 0;
352   t->pass_count  = 0;
353   t->addr_string = NULL;
354
355   /* Add this tracepoint to the end of the chain
356      so that a list of tracepoints will come out in order
357      of increasing numbers.  */
358
359   tc = tracepoint_chain;
360   if (tc == 0)
361     tracepoint_chain = t;
362   else
363     {
364       while (tc->next)
365         tc = tc->next;
366       tc->next = t;
367     }
368   discard_cleanups (old_chain);
369   return t;
370 }
371
372 /* Set a tracepoint according to ARG (function, linenum or *address) */
373 static void
374 trace_command (arg, from_tty)
375      char *arg;
376      int from_tty;
377 {
378   char **canonical = (char **)NULL;
379   struct symtabs_and_lines sals;
380   struct symtab_and_line sal;
381   struct tracepoint *t;
382   char *addr_start = 0, *addr_end = 0;
383   int i;
384
385   if (!arg || !*arg)
386     error ("trace command requires an argument");
387
388   if (from_tty && info_verbose)
389     printf_filtered ("TRACE %s\n", arg);
390
391   addr_start = arg;
392   sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical);
393   addr_end   = arg;
394   if (! sals.nelts) 
395     return;     /* ??? Presumably decode_line_1 has already warned? */
396
397   /* Resolve all line numbers to PC's */
398   for (i = 0; i < sals.nelts; i++)
399     resolve_sal_pc (&sals.sals[i]);
400
401   /* Now set all the tracepoints.  */
402   for (i = 0; i < sals.nelts; i++)
403     {
404       sal = sals.sals[i];
405
406       t = set_raw_tracepoint (sal);
407       set_tracepoint_count (tracepoint_count + 1);
408       t->number = tracepoint_count;
409
410       /* If a canonical line spec is needed use that instead of the
411          command string.  */
412       if (canonical != (char **)NULL && canonical[i] != NULL)
413         t->addr_string = canonical[i];
414       else if (addr_start)
415         t->addr_string = savestring (addr_start, addr_end - addr_start);
416
417       trace_mention (t);
418
419       /* Let the UI know of any additions */
420       if (create_tracepoint_hook)
421         create_tracepoint_hook (t);
422     }
423
424   if (sals.nelts > 1)
425     {
426       printf_filtered ("Multiple tracepoints were set.\n");
427       printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
428     }
429 }
430
431 /* Tell the user we have just set a tracepoint TP. */
432
433 static void
434 trace_mention (tp)
435      struct tracepoint *tp;
436 {
437   printf_filtered ("Tracepoint %d", tp->number);
438
439   if (addressprint || (tp->source_file == NULL))
440     {
441       printf_filtered (" at ");
442       print_address_numeric (tp->address, 1, gdb_stdout);
443     }
444   if (tp->source_file)
445     printf_filtered (": file %s, line %d.",
446                      tp->source_file, tp->line_number);
447
448   printf_filtered ("\n");
449 }
450
451 /* Print information on tracepoint number TPNUM_EXP, or all if omitted.  */
452
453 static void
454 tracepoints_info (tpnum_exp, from_tty)
455      char *tpnum_exp;
456      int from_tty;
457 {
458   struct tracepoint *t;
459   struct action_line *action;
460   int found_a_tracepoint = 0;
461   char wrap_indent[80];
462   struct symbol *sym;
463   int tpnum = -1;
464
465   if (tpnum_exp)
466     tpnum = parse_and_eval_address (tpnum_exp);
467
468   ALL_TRACEPOINTS (t)
469     if (tpnum == -1 || tpnum == t->number)
470       {
471         extern int addressprint;        /* print machine addresses? */
472
473         if (!found_a_tracepoint++)
474           {
475             printf_filtered ("Num Enb ");
476             if (addressprint)
477               printf_filtered ("Address    ");
478             printf_filtered ("PassC StepC What\n");
479           }
480         strcpy (wrap_indent, "                           ");
481         if (addressprint)
482           strcat (wrap_indent, "           ");
483
484         printf_filtered ("%-3d %-3s ", t->number, 
485                          t->enabled == enabled ? "y" : "n");
486         if (addressprint)
487           printf_filtered ("%s ", 
488                            local_hex_string_custom ((unsigned long) t->address,
489                                                     "08l"));
490         printf_filtered ("%-5d %-5d ", t->pass_count, t->step_count);
491
492         if (t->source_file)
493           {
494             sym = find_pc_sect_function (t->address, t->section);
495             if (sym)
496               {
497                 fputs_filtered ("in ", gdb_stdout);
498                 fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
499                 wrap_here (wrap_indent);
500                 fputs_filtered (" at ", gdb_stdout);
501               }
502             fputs_filtered (t->source_file, gdb_stdout);
503             printf_filtered (":%d", t->line_number);
504           }
505         else
506           print_address_symbolic (t->address, gdb_stdout, demangle, " ");
507
508         printf_filtered ("\n");
509         if (t->actions)
510           {
511             printf_filtered ("  Actions for tracepoint %d: \n", t->number);
512             for (action = t->actions; action; action = action->next)
513               {
514                 printf_filtered ("\t%s\n", action->action);
515               }
516           }
517       }
518   if (!found_a_tracepoint)
519     {
520       if (tpnum == -1)
521         printf_filtered ("No tracepoints.\n");
522       else
523         printf_filtered ("No tracepoint number %d.\n", tpnum);
524     }
525 }
526
527 /* Optimization: the code to parse an enable, disable, or delete TP command
528    is virtually identical except for whether it performs an enable, disable,
529    or delete.  Therefore I've combined them into one function with an opcode.
530    */
531 enum tracepoint_opcode 
532 {
533   enable, 
534   disable,
535   delete
536 };
537
538 /* This function implements enable, disable and delete. */
539 static void
540 tracepoint_operation (t, from_tty, opcode)
541      struct tracepoint *t;
542      int from_tty;
543      enum tracepoint_opcode opcode;
544 {
545   struct tracepoint *t2;
546
547   switch (opcode) {
548   case enable:
549     t->enabled = enabled;
550     if (modify_tracepoint_hook)
551       modify_tracepoint_hook (t);
552     break;
553   case disable:
554     t->enabled = disabled;
555     if (modify_tracepoint_hook)
556       modify_tracepoint_hook (t);
557     break;
558   case delete:
559     if (tracepoint_chain == t)
560       tracepoint_chain = t->next;
561
562     ALL_TRACEPOINTS (t2)
563       if (t2->next == t)
564         {
565           t2->next = t->next;
566           break;
567         }
568
569     /* Let the UI know of any deletions */
570     if (delete_tracepoint_hook)
571       delete_tracepoint_hook (t);
572
573     if (t->addr_string)
574       free (t->addr_string);
575     if (t->source_file)
576       free (t->source_file);
577     if (t->actions)
578       free_actions (t);
579
580     free (t);
581     break;
582   }
583 }
584
585 /* Utility: parse a tracepoint number and look it up in the list.  */
586 struct tracepoint *
587 get_tracepoint_by_number (arg)
588      char **arg;
589 {
590   struct tracepoint *t;
591   char *end, *copy;
592   value_ptr val;
593   int tpnum;
594
595   if (arg == 0)
596     error ("Bad tracepoint argument");
597
598   if (*arg == 0 || **arg == 0)  /* empty arg means refer to last tp */
599     tpnum = tracepoint_count;
600   else if (**arg == '$')        /* handle convenience variable */
601     {
602       /* Make a copy of the name, so we can null-terminate it
603          to pass to lookup_internalvar().  */
604       end = *arg + 1;
605       while (isalnum(*end) || *end == '_')
606         end++;
607       copy = (char *) alloca (end - *arg);
608       strncpy (copy, *arg + 1, (end - *arg - 1));
609       copy[end - *arg - 1] = '\0';
610       *arg = end;
611
612       val = value_of_internalvar (lookup_internalvar (copy));
613       if (TYPE_CODE( VALUE_TYPE (val)) != TYPE_CODE_INT)
614         error ("Convenience variable must have integral type.");
615       tpnum = (int) value_as_long (val);
616     }
617   else          /* handle tracepoint number */
618     {
619       tpnum = strtol (*arg, arg, 0);
620       if (tpnum == 0)           /* possible strtol failure */
621         while (**arg && !isspace (**arg))
622           (*arg)++;             /* advance to next white space, if any */
623     }
624   ALL_TRACEPOINTS (t)
625     if (t->number == tpnum)
626       {
627         return t;
628       }
629   printf_unfiltered ("No tracepoint number %d.\n", tpnum);
630   return NULL;
631 }
632
633 /* Utility: parse a list of tracepoint numbers, and call a func for each. */
634 static void
635 map_args_over_tracepoints (args, from_tty, opcode)
636      char *args;
637      int from_tty;
638      enum tracepoint_opcode opcode;
639 {
640   struct tracepoint *t, *tmp;
641   int tpnum;
642   char *cp;
643
644   if (args == 0 || *args == 0)  /* do them all */
645     ALL_TRACEPOINTS_SAFE (t, tmp)
646       tracepoint_operation (t, from_tty, opcode);
647   else
648     while (*args)
649       {
650         QUIT;           /* give user option to bail out with ^C */
651         t = get_tracepoint_by_number (&args);
652         if (t)
653           tracepoint_operation (t, from_tty, opcode);
654         while (*args == ' ' || *args == '\t')
655           args++;
656       }
657 }
658
659 /* The 'enable trace' command enables tracepoints.  Not supported by all targets.  */
660 static void
661 enable_trace_command (args, from_tty)
662      char *args;
663      int from_tty;
664 {
665   dont_repeat ();
666   map_args_over_tracepoints (args, from_tty, enable);
667 }
668
669 /* The 'disable trace' command enables tracepoints.  Not supported by all targets.  */
670 static void
671 disable_trace_command (args, from_tty)
672      char *args;
673      int from_tty;
674 {
675   dont_repeat ();
676   map_args_over_tracepoints (args, from_tty, disable);
677 }
678
679 /* Remove a tracepoint (or all if no argument) */
680 static void
681 delete_trace_command (args, from_tty)
682      char *args;
683      int from_tty;
684 {
685   dont_repeat ();
686   if (!args || !*args)          /* No args implies all tracepoints; */
687     if (from_tty)               /* confirm only if from_tty... */
688       if (tracepoint_chain)     /* and if there are tracepoints to delete! */
689         if (!query ("Delete all tracepoints? "))
690           return;
691
692   map_args_over_tracepoints (args, from_tty, delete);
693 }
694
695 /* Set passcount for tracepoint.
696
697    First command argument is passcount, second is tracepoint number.
698    If tracepoint number omitted, apply to most recently defined.
699    Also accepts special argument "all".  */
700
701 static void
702 trace_pass_command (args, from_tty)
703      char *args;
704      int from_tty;
705 {
706   struct tracepoint *t1 = (struct tracepoint *) -1, *t2;
707   unsigned long count;
708
709   if (args == 0 || *args == 0)
710     error ("PASS command requires an argument (count + optional TP num)");
711
712   count = strtoul (args, &args, 10);    /* count comes first, then TP num */
713
714   while (*args && isspace (*args))
715     args++;
716
717   if (*args && strncasecmp (args, "all", 3) == 0)
718     args += 3;  /* skip special argument "all" */
719   else
720     t1 = get_tracepoint_by_number (&args);
721
722   if (*args)
723     error ("Junk at end of arguments.");
724
725   if (t1 == NULL)
726     return;     /* error, bad tracepoint number */
727
728   ALL_TRACEPOINTS (t2)
729     if (t1 == (struct tracepoint *) -1 || t1 == t2)
730       {
731         t2->pass_count = count;
732         if (modify_tracepoint_hook)
733           modify_tracepoint_hook (t2);
734         if (from_tty)
735           printf_filtered ("Setting tracepoint %d's passcount to %d\n", 
736                            t2->number, count);
737       }
738 }
739
740 /* ACTIONS functions: */
741
742 /* Prototypes for action-parsing utility commands  */
743 static void  read_actions PARAMS((struct tracepoint *));
744 static char *parse_and_eval_memrange PARAMS ((char *,
745                                               CORE_ADDR, 
746                                               long *,
747                                               bfd_signed_vma *,
748                                               long *));
749
750 /* The three functions:
751         collect_pseudocommand, 
752         while_stepping_pseudocommand, and 
753         end_actions_pseudocommand
754    are placeholders for "commands" that are actually ONLY to be used
755    within a tracepoint action list.  If the actual function is ever called,
756    it means that somebody issued the "command" at the top level,
757    which is always an error.  */
758
759 static void 
760 end_actions_pseudocommand (args, from_tty)
761      char *args;
762      int from_tty;
763 {
764   error ("This command cannot be used at the top level.");
765 }
766
767 static void
768 while_stepping_pseudocommand (args, from_tty)
769      char *args;
770      int from_tty;
771 {
772   error ("This command can only be used in a tracepoint actions list.");
773 }
774
775 static void
776 collect_pseudocommand (args, from_tty)
777      char *args;
778      int from_tty;
779 {
780   error ("This command can only be used in a tracepoint actions list.");
781 }
782
783 /* Enter a list of actions for a tracepoint.  */
784 static void
785 trace_actions_command (args, from_tty)
786      char *args;
787      int from_tty;
788 {
789   struct tracepoint *t;
790   char *actions;
791   char tmpbuf[128];
792   char *end_msg = "End with a line saying just \"end\".";
793
794   t = get_tracepoint_by_number (&args);
795   if (t)
796     {
797       sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
798                t->number);
799
800       if (from_tty)
801         {
802           if (readline_begin_hook)
803             (*readline_begin_hook) ("%s  %s\n", tmpbuf, end_msg);
804           else if (input_from_terminal_p ())
805             printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
806         }
807
808       free_actions (t);
809       t->step_count = 0;        /* read_actions may set this */
810       read_actions (t);
811
812       if (readline_end_hook)
813         (*readline_end_hook) ();
814
815       /* tracepoints_changed () */
816     }
817   /* else error, just return; */
818 }
819
820 /* worker function */
821 static void
822 read_actions (t)
823      struct tracepoint *t;
824 {
825   char *line;
826   char *prompt1 = "> ", *prompt2 = "  > ";
827   char *prompt = prompt1;
828   enum actionline_type linetype;
829   extern FILE *instream;
830   struct action_line *next = NULL, *temp;
831   struct cleanup *old_chain;
832
833   /* Control-C quits instantly if typed while in this loop
834      since it should not wait until the user types a newline.  */
835   immediate_quit++;
836 #ifdef STOP_SIGNAL
837   if (job_control)
838     {
839       if (async_p)
840         signal (STOP_SIGNAL, handle_stop_sig);
841       else
842         signal (STOP_SIGNAL, stop_sig);
843     } 
844 #endif
845   old_chain = make_cleanup ((make_cleanup_func) free_actions, (void *) t);
846   while (1)
847     {
848       /* Make sure that all output has been output.  Some machines may let
849          you get away with leaving out some of the gdb_flush, but not all.  */
850       wrap_here ("");
851       gdb_flush (gdb_stdout);
852       gdb_flush (gdb_stderr);
853
854       if (readline_hook && instream == NULL)
855         line = (*readline_hook) (prompt);
856       else if (instream == stdin && ISATTY (instream))
857         {
858           line = readline (prompt);
859           if (line && *line)            /* add it to command history */
860             add_history (line);
861         }
862       else
863         line = gdb_readline (0);
864
865       linetype = validate_actionline (&line, t);
866       if (linetype == BADLINE)
867         continue;       /* already warned -- collect another line */
868
869       temp = xmalloc (sizeof (struct action_line));
870       temp->next = NULL;
871       temp->action = line;
872
873       if (next == NULL)         /* first action for this tracepoint? */
874         t->actions = next = temp;
875       else
876         {
877           next->next = temp;
878           next = temp;
879         }
880
881       if (linetype == STEPPING) /* begin "while-stepping" */
882         {
883           if (prompt == prompt2)
884             {
885               warning ("Already processing 'while-stepping'");
886               continue;
887             }
888           else
889             prompt = prompt2;   /* change prompt for stepping actions */
890         }
891       else if (linetype == END)
892         {
893           if (prompt == prompt2)
894             {
895               prompt = prompt1; /* end of single-stepping actions */
896             }
897           else
898             { /* end of actions */
899               if (t->actions->next == NULL)
900                 {
901                   /* an "end" all by itself with no other actions means
902                      this tracepoint has no actions.  Discard empty list. */
903                   free_actions (t);
904                 }
905               break;
906             }
907         }
908     }
909 #ifdef STOP_SIGNAL
910   if (job_control)
911     signal (STOP_SIGNAL, SIG_DFL);
912 #endif
913   immediate_quit = 0;
914   discard_cleanups (old_chain);
915 }
916
917 /* worker function */
918 enum actionline_type
919 validate_actionline (line, t)
920      char **line;
921      struct tracepoint *t;
922 {
923   struct cmd_list_element *c;
924   struct expression *exp = NULL;
925   value_ptr temp, temp2;
926   struct cleanup *old_chain = NULL;
927   char *p;
928
929   for (p = *line; isspace (*p); )
930     p++;
931
932   /* symbol lookup etc. */
933   if (*p == '\0')       /* empty line: just prompt for another line. */
934     return BADLINE;
935
936   if (*p == '#')        /* comment line */
937     return GENERIC;
938
939   c = lookup_cmd (&p, cmdlist, "", -1, 1);
940   if (c == 0)
941     {
942       warning ("'%s' is not an action that I know, or is ambiguous.", p);
943       return BADLINE;
944     }
945     
946   if (c->function.cfunc == collect_pseudocommand)
947     {
948       struct agent_expr *aexpr;
949       struct agent_reqs areqs;
950
951       do {                      /* repeat over a comma-separated list */
952         QUIT;                   /* allow user to bail out with ^C */
953         while (isspace (*p))
954           p++;
955
956         if (*p == '$')                  /* look for special pseudo-symbols */
957           {
958             long typecode, size;
959             bfd_signed_vma offset;
960
961             if ((0 == strncasecmp ("reg", p + 1, 3)) ||
962                 (0 == strncasecmp ("arg", p + 1, 3)) ||
963                 (0 == strncasecmp ("loc", p + 1, 3)))
964               {
965                 p = strchr (p, ',');
966                 continue;
967               }
968             /* else fall thru, treat p as an expression and parse it! */
969           }
970         exp   = parse_exp_1 (&p, block_for_pc (t->address), 1);
971         old_chain = make_cleanup ((make_cleanup_func) free_current_contents, 
972                                   &exp);
973
974         if (exp->elts[0].opcode == OP_VAR_VALUE)
975           {
976             if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
977               {
978                 warning ("%s is constant (value %d): will not be collected.",
979                          SYMBOL_NAME (exp->elts[2].symbol),
980                          SYMBOL_VALUE (exp->elts[2].symbol));
981                 return BADLINE;
982               }
983             else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
984               {
985                 warning ("%s is optimized away and cannot be collected.",
986                          SYMBOL_NAME (exp->elts[2].symbol));
987                 return BADLINE;
988               }
989           }
990
991         /* we have something to collect, make sure that the expr to
992            bytecode translator can handle it and that it's not too long */
993         aexpr = gen_trace_for_expr (t->address, exp);
994         (void) make_cleanup ((make_cleanup_func) free_agent_expr, aexpr);
995
996         if (aexpr->len > MAX_AGENT_EXPR_LEN)
997           error ("expression too complicated, try simplifying");
998
999         ax_reqs(aexpr, &areqs);
1000         (void) make_cleanup (free, areqs.reg_mask);
1001
1002         if (areqs.flaw != agent_flaw_none)
1003           error ("malformed expression");
1004
1005         if (areqs.min_height < 0)
1006           error ("gdb: Internal error: expression has min height < 0");
1007
1008         if (areqs.max_height > 20)
1009           error ("expression too complicated, try simplifying");
1010
1011         do_cleanups (old_chain);
1012       } while (p && *p++ == ',');
1013       return GENERIC;
1014     }
1015   else if (c->function.cfunc == while_stepping_pseudocommand)
1016     {
1017       char *steparg;    /* in case warning is necessary */
1018
1019       while (isspace (*p))
1020         p++;
1021       steparg = p;
1022
1023       if (*p == '\0' ||
1024           (t->step_count = strtol (p, &p, 0)) == 0)
1025         {
1026           warning ("bad step-count: command ignored.", *line);
1027           return BADLINE;
1028         }
1029       return STEPPING;
1030     }
1031   else if (c->function.cfunc == end_actions_pseudocommand)
1032     return END;
1033   else
1034     {
1035       warning ("'%s' is not a supported tracepoint action.", *line);
1036       return BADLINE;
1037     }
1038 }
1039
1040 /* worker function */
1041 void 
1042 free_actions (t)
1043      struct tracepoint *t;
1044 {
1045   struct action_line *line, *next;
1046
1047   for (line = t->actions; line; line = next)
1048     {
1049       next = line->next;
1050       if (line->action) 
1051         free (line->action);
1052       free (line);
1053     }
1054   t->actions = NULL;
1055 }
1056
1057 struct memrange {
1058   int type;             /* 0 for absolute memory range, else basereg number */
1059   bfd_signed_vma start;
1060   bfd_signed_vma end;
1061 };
1062
1063 struct collection_list {
1064   unsigned char regs_mask[8];   /* room for up to 256 regs */
1065   long listsize;
1066   long next_memrange;
1067   struct memrange *list;
1068   long aexpr_listsize;          /* size of array pointed to by expr_list elt */
1069   long next_aexpr_elt;
1070   struct agent_expr **aexpr_list;
1071   
1072 } tracepoint_list, stepping_list;
1073
1074 /* MEMRANGE functions: */
1075
1076 static int memrange_cmp PARAMS ((const void *, const void *));
1077
1078 /* compare memranges for qsort */
1079 static int
1080 memrange_cmp (va, vb)
1081      const void *va;
1082      const void *vb;
1083 {
1084   const struct memrange *a = va, *b = vb;
1085
1086   if (a->type < b->type)
1087     return -1;
1088   if (a->type > b->type)
1089     return  1;
1090   if (a->type == 0)
1091     {
1092       if ((bfd_vma) a->start  < (bfd_vma) b->start)  return -1;
1093       if ((bfd_vma) a->start  > (bfd_vma) b->start)  return  1;
1094     }
1095   else
1096     {
1097       if (a->start  < b->start)
1098         return -1;
1099       if (a->start  > b->start)
1100         return  1;
1101     }
1102   return 0;
1103 }
1104
1105 /* Sort the memrange list using qsort, and merge adjacent memranges */
1106 static void
1107 memrange_sortmerge (memranges)
1108      struct collection_list *memranges;
1109 {
1110   int a, b;
1111
1112   qsort (memranges->list, memranges->next_memrange, 
1113          sizeof (struct memrange), memrange_cmp);
1114   if (memranges->next_memrange > 0)
1115     {
1116       for (a = 0, b = 1; b < memranges->next_memrange; b++)
1117         {
1118           if (memranges->list[a].type == memranges->list[b].type &&
1119               memranges->list[b].start - memranges->list[a].end <= 
1120               MAX_REGISTER_VIRTUAL_SIZE)
1121             {
1122               /* memrange b starts before memrange a ends; merge them.  */
1123               if (memranges->list[b].end > memranges->list[a].end)
1124                 memranges->list[a].end = memranges->list[b].end;
1125               continue;         /* next b, same a */
1126             }
1127           a++;                  /* next a */
1128           if (a != b)
1129             memcpy (&memranges->list[a], &memranges->list[b], 
1130                     sizeof (struct memrange));
1131         }
1132       memranges->next_memrange = a + 1;
1133     }
1134 }
1135
1136 /* Add a register to a collection list */
1137 static void
1138 add_register (collection, regno)
1139      struct collection_list *collection;
1140      unsigned long regno;
1141 {
1142   if (info_verbose)
1143     printf_filtered ("collect register %d\n", regno);
1144   if (regno > (8 * sizeof (collection->regs_mask)))
1145     error ("Internal: register number %d too large for tracepoint",
1146            regno);
1147   collection->regs_mask [regno / 8] |= 1 << (regno  % 8);
1148 }
1149
1150 /* Add a memrange to a collection list */
1151 static void
1152 add_memrange (memranges, type, base, len)
1153      struct collection_list *memranges;
1154      int type;
1155      bfd_signed_vma base;
1156      unsigned long len;
1157 {
1158   if (info_verbose)
1159     printf_filtered ("(%d,0x%x,%d)\n", type, base, len);
1160   /* type: 0 == memory, n == basereg */
1161   memranges->list[memranges->next_memrange].type  = type;
1162   /* base: addr if memory, offset if reg relative. */
1163   memranges->list[memranges->next_memrange].start = base;
1164   /* len: we actually save end (base + len) for convenience */
1165   memranges->list[memranges->next_memrange].end   = base + len;
1166   memranges->next_memrange++;
1167   if (memranges->next_memrange >= memranges->listsize)
1168     {
1169       memranges->listsize *= 2;
1170       memranges->list = xrealloc (memranges->list, 
1171                                   memranges->listsize);
1172     }
1173
1174   if (type != -1)       /* better collect the base register! */
1175     add_register (memranges, type);
1176 }
1177
1178 /* Add a symbol to a collection list */
1179 static void
1180 collect_symbol (collect, sym, frame_regno, frame_offset)
1181      struct collection_list *collect;
1182      struct symbol *sym;
1183      long frame_regno;
1184      long frame_offset;
1185 {
1186   unsigned long  len;
1187   unsigned long  reg;
1188   bfd_signed_vma offset;
1189
1190   len  = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
1191   switch (SYMBOL_CLASS (sym)) {
1192   default:
1193     printf_filtered ("%s: don't know symbol class %d\n",
1194                      SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
1195     break;
1196   case LOC_CONST:
1197     printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1198                      SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
1199     break;
1200   case LOC_STATIC:
1201     offset = SYMBOL_VALUE_ADDRESS (sym); 
1202     if (info_verbose)
1203       printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
1204                        SYMBOL_NAME (sym), len, offset);
1205     add_memrange (collect, -1, offset, len);    /* 0 == memory */
1206     break;
1207   case LOC_REGISTER:
1208   case LOC_REGPARM:
1209     reg = SYMBOL_VALUE (sym); 
1210     if (info_verbose)
1211       printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
1212     add_register (collect, reg);
1213     /* check for doubles stored in two registers */
1214     /* FIXME: how about larger types stored in 3 or more regs? */
1215     if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
1216         len > REGISTER_RAW_SIZE (reg))
1217       add_register (collect, reg + 1);
1218     break;
1219   case LOC_REF_ARG:
1220     printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
1221     printf_filtered ("       (will not collect %s)\n", 
1222                      SYMBOL_NAME (sym));
1223     break;
1224   case LOC_ARG:
1225     reg    = frame_regno;
1226     offset = frame_offset + SYMBOL_VALUE (sym);
1227     if (info_verbose)
1228       {
1229         printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1230                          SYMBOL_NAME (sym), len);
1231         printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
1232       }
1233     add_memrange (collect, reg, offset, len);
1234     break;
1235   case LOC_REGPARM_ADDR:
1236     reg = SYMBOL_VALUE (sym);
1237     offset = 0;
1238     if (info_verbose)
1239       {
1240         printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset",
1241                          SYMBOL_NAME (sym), len);
1242         printf_filtered (" %d from reg %d\n", offset, reg);
1243       }
1244     add_memrange (collect, reg, offset, len);
1245     break;
1246   case LOC_LOCAL:
1247   case LOC_LOCAL_ARG:
1248     reg    = frame_regno;
1249     offset = frame_offset + SYMBOL_VALUE (sym);
1250     if (info_verbose)
1251       {
1252         printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1253                          SYMBOL_NAME (sym), len);
1254         printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
1255       }
1256     add_memrange (collect, reg, offset, len);
1257     break;
1258   case LOC_BASEREG:
1259   case LOC_BASEREG_ARG:
1260     reg = SYMBOL_BASEREG (sym);
1261     offset  = SYMBOL_VALUE (sym);
1262     if (info_verbose)
1263       {
1264         printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n", 
1265                          SYMBOL_NAME (sym), len, offset, reg);
1266       }
1267     add_memrange (collect, reg, offset, len);
1268     break;
1269   case LOC_UNRESOLVED:
1270     printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
1271     break;
1272   case LOC_OPTIMIZED_OUT:
1273     printf_filtered ("%s has been optimized out of existance.\n",
1274                      SYMBOL_NAME (sym));
1275     break;
1276   }
1277 }
1278
1279 /* Add all locals (or args) symbols to collection list */
1280 static void
1281 add_local_symbols (collect, pc, frame_regno, frame_offset, type)
1282      struct collection_list *collect;
1283      CORE_ADDR pc;
1284      long frame_regno;
1285      long frame_offset;
1286      int type;
1287 {
1288   struct symbol *sym;
1289   struct block  *block;
1290   int i, nsyms, count = 0;
1291
1292   block = block_for_pc (pc);
1293   while (block != 0)
1294     {
1295       QUIT;                             /* allow user to bail out with ^C */
1296       nsyms = BLOCK_NSYMS (block);
1297       for (i = 0; i < nsyms; i++)
1298         {
1299           sym = BLOCK_SYM (block, i);
1300           switch (SYMBOL_CLASS (sym)) {
1301           case LOC_LOCAL:
1302           case LOC_STATIC:
1303           case LOC_REGISTER:
1304           case LOC_BASEREG:
1305             if (type == 'L')    /* collecting Locals */
1306               {
1307                 count++;
1308                 collect_symbol (collect, sym, frame_regno, frame_offset);
1309               }
1310             break;
1311           case LOC_ARG:
1312           case LOC_LOCAL_ARG:
1313           case LOC_REF_ARG:
1314           case LOC_REGPARM:
1315           case LOC_REGPARM_ADDR:
1316           case LOC_BASEREG_ARG:
1317             if (type == 'A')    /* collecting Arguments */
1318               {
1319                 count++;
1320                 collect_symbol (collect, sym, frame_regno, frame_offset);
1321               }
1322           }
1323         }
1324       if (BLOCK_FUNCTION (block))
1325         break;
1326       else
1327         block = BLOCK_SUPERBLOCK (block);
1328     }
1329   if (count == 0)
1330     warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
1331 }
1332
1333 /* worker function */
1334 static void
1335 clear_collection_list (list)
1336      struct collection_list *list;
1337 {
1338   int ndx;
1339
1340   list->next_memrange = 0;
1341   for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
1342     {
1343       free_agent_expr(list->aexpr_list[ndx]);
1344       list->aexpr_list[ndx] = NULL;
1345     }
1346   list->next_aexpr_elt = 0;
1347   memset (list->regs_mask, 0, sizeof (list->regs_mask));
1348 }
1349
1350 /* reduce a collection list to string form (for gdb protocol) */
1351 static char **
1352 stringify_collection_list (list, string)
1353      struct collection_list *list;
1354      char *string;
1355 {
1356   char temp_buf[2048];
1357   int count;
1358   int ndx = 0;
1359   char *(*str_list)[];
1360   char *end;
1361   long  i;
1362
1363   count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
1364   str_list = (char *(*)[])xmalloc(count * sizeof (char *));
1365
1366   for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1367     if (list->regs_mask[i] != 0)        /* skip leading zeroes in regs_mask */
1368       break;
1369   if (list->regs_mask[i] != 0)  /* prepare to send regs_mask to the stub */
1370     {
1371       if (info_verbose)
1372         printf_filtered ("\nCollecting registers (mask): 0x");
1373       end = temp_buf;
1374       *end++='R';
1375       for (; i >= 0; i--)
1376         {
1377           QUIT;                         /* allow user to bail out with ^C */
1378           if (info_verbose)
1379             printf_filtered ("%02X", list->regs_mask[i]);
1380           sprintf (end,  "%02X", list->regs_mask[i]);
1381           end += 2;
1382         }
1383       (*str_list)[ndx] = savestring(temp_buf, end - temp_buf);
1384       ndx++;
1385     }
1386   if (info_verbose)
1387     printf_filtered ("\n");
1388   if (list->next_memrange > 0 && info_verbose)
1389     printf_filtered ("Collecting memranges: \n");
1390   for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
1391     {
1392       QUIT;                     /* allow user to bail out with ^C */
1393       if (info_verbose)
1394         printf_filtered ("(%d, 0x%x, %d)\n", 
1395                          list->list[i].type, 
1396                          list->list[i].start, 
1397                          list->list[i].end - list->list[i].start);
1398       if (count + 27 > MAX_AGENT_EXPR_LEN)
1399         {
1400           (*str_list)[ndx] = savestring(temp_buf, count);
1401           ndx++;
1402           count = 0;
1403           end = temp_buf;
1404         }
1405       sprintf (end, "M%X,%X,%X", 
1406                list->list[i].type, 
1407                list->list[i].start, 
1408                list->list[i].end - list->list[i].start);
1409       count += strlen (end);
1410       end += strlen (end);
1411     }
1412
1413   for (i = 0; i < list->next_aexpr_elt; i++)
1414     {
1415       QUIT;                     /* allow user to bail out with ^C */
1416       if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
1417         {
1418           (*str_list)[ndx] = savestring(temp_buf, count);
1419           ndx++;
1420           count = 0;
1421           end = temp_buf;
1422         }
1423       sprintf (end, "X%08X,", list->aexpr_list[i]->len);
1424       end += 10;                /* 'X' + 8 hex digits + ',' */
1425       count += 10;
1426
1427       end = mem2hex(list->aexpr_list[i]->buf, end, list->aexpr_list[i]->len);
1428       count += 2 * list->aexpr_list[i]->len;
1429     }
1430
1431   if (count != 0)
1432     {
1433       (*str_list)[ndx] = savestring(temp_buf, count);
1434       ndx++;
1435       count = 0;
1436       end = temp_buf;
1437     }
1438   (*str_list)[ndx] = NULL;
1439
1440   if (ndx == 0)
1441     return NULL;
1442   else
1443     return *str_list;
1444 }
1445
1446 static void
1447 free_actions_list_cleanup_wrapper (al)
1448      void *al;
1449 {
1450   free_actions_list (al);
1451 }
1452
1453 static void
1454 free_actions_list(actions_list)
1455      char **actions_list;
1456 {
1457   int ndx;
1458
1459   if (actions_list == 0)
1460     return;
1461
1462   for (ndx = 0; actions_list[ndx]; ndx++)
1463     free(actions_list[ndx]);
1464
1465   free(actions_list);
1466 }
1467
1468 /* render all actions into gdb protocol */
1469 static void
1470 encode_actions (t, tdp_actions, stepping_actions)
1471      struct tracepoint  *t;
1472      char              ***tdp_actions;
1473      char              ***stepping_actions;
1474 {
1475   static char        tdp_buff[2048], step_buff[2048];
1476   char               *action_exp;
1477   struct expression  *exp = NULL;
1478   struct action_line *action;
1479   bfd_signed_vma      offset;
1480   long                i;
1481   value_ptr           tempval;
1482   struct collection_list  *collect;
1483   struct cmd_list_element *cmd;
1484   struct agent_expr *aexpr;
1485   long                frame_reg, frame_offset;
1486
1487
1488   clear_collection_list (&tracepoint_list);
1489   clear_collection_list (&stepping_list);
1490   collect = &tracepoint_list;
1491
1492   *tdp_actions = NULL;
1493   *stepping_actions = NULL;
1494
1495   TARGET_VIRTUAL_FRAME_POINTER (t->address, &frame_reg, &frame_offset);
1496
1497   for (action = t->actions; action; action = action->next)
1498     {
1499       QUIT;                     /* allow user to bail out with ^C */
1500       action_exp = action->action;
1501       while (isspace (*action_exp))
1502         action_exp++;
1503
1504       if (*action_exp == '#')   /* comment line */
1505         return;
1506
1507       cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
1508       if (cmd == 0)
1509         error ("Bad action list item: %s", action_exp);
1510
1511       if (cmd->function.cfunc == collect_pseudocommand)
1512         {
1513           do {  /* repeat over a comma-separated list */
1514             QUIT;               /* allow user to bail out with ^C */
1515             while (isspace (*action_exp))
1516               action_exp++;
1517
1518             if (0 == strncasecmp ("$reg", action_exp, 4))
1519               {
1520                 for (i = 0; i < NUM_REGS; i++)
1521                   add_register (collect, i);
1522                 action_exp = strchr (action_exp, ','); /* more? */
1523               }
1524             else if (0 == strncasecmp ("$arg", action_exp, 4))
1525               {
1526                 add_local_symbols (collect, 
1527                                    t->address, 
1528                                    frame_reg,
1529                                    frame_offset,
1530                                    'A');
1531                 action_exp = strchr (action_exp, ','); /* more? */
1532               }
1533             else if (0 == strncasecmp ("$loc", action_exp, 4))
1534               {
1535                 add_local_symbols (collect, 
1536                                    t->address, 
1537                                    frame_reg,
1538                                    frame_offset,
1539                                    'L');
1540                 action_exp = strchr (action_exp, ','); /* more? */
1541               }
1542             else
1543               {
1544                 unsigned long addr, len;
1545                 struct cleanup *old_chain = NULL;
1546                 struct cleanup *old_chain1 = NULL;
1547                 struct agent_reqs areqs;
1548
1549                 exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
1550                 old_chain = make_cleanup ((make_cleanup_func) 
1551                                           free_current_contents, &exp);
1552
1553                 switch (exp->elts[0].opcode) {
1554                 case OP_REGISTER:
1555                   i = exp->elts[1].longconst;
1556                   if (info_verbose)
1557                     printf_filtered ("OP_REGISTER: ");
1558                   add_register (collect, i);
1559                   break;
1560
1561                 case UNOP_MEMVAL:
1562                   /* safe because we know it's a simple expression */
1563                   tempval = evaluate_expression (exp);
1564                   addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
1565                   len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
1566                   add_memrange (collect, -1, addr, len);
1567                   break;
1568
1569                 case OP_VAR_VALUE:
1570                   collect_symbol (collect, 
1571                                   exp->elts[2].symbol,
1572                                   frame_reg,
1573                                   frame_offset);
1574                   break;
1575
1576                 default:        /* full-fledged expression */
1577                   aexpr = gen_trace_for_expr (t->address, exp);
1578
1579                   old_chain1 = make_cleanup ((make_cleanup_func) 
1580                                              free_agent_expr, aexpr);
1581
1582                   ax_reqs (aexpr, &areqs);
1583                   if (areqs.flaw != agent_flaw_none)
1584                     error ("malformed expression");
1585
1586                   if (areqs.min_height < 0)
1587                     error ("gdb: Internal error: expression has min height < 0");
1588                   if (areqs.max_height > 20)
1589                     error ("expression too complicated, try simplifying");
1590
1591                   discard_cleanups (old_chain1);
1592                   add_aexpr (collect, aexpr);
1593
1594                   /* take care of the registers */
1595                   if (areqs.reg_mask_len > 0)
1596                     {
1597                       int ndx1;
1598                       int ndx2;
1599
1600                       for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
1601                         {
1602                           QUIT;         /* allow user to bail out with ^C */
1603                           if (areqs.reg_mask[ndx1] != 0)
1604                             {
1605                               /* assume chars have 8 bits */
1606                               for (ndx2 = 0; ndx2 < 8; ndx2++)
1607                                 if (areqs.reg_mask[ndx1] & (1 << ndx2))
1608                                   /* it's used -- record it */
1609                                   add_register (collect, ndx1 * 8 + ndx2);
1610                             }
1611                         }
1612                     }
1613                   break;
1614                 }       /* switch */
1615                 do_cleanups (old_chain);
1616               }         /* do */
1617           } while (action_exp && *action_exp++ == ',');
1618         }               /* if */
1619       else if (cmd->function.cfunc == while_stepping_pseudocommand)
1620         {
1621           collect = &stepping_list;
1622         }
1623       else if (cmd->function.cfunc == end_actions_pseudocommand)
1624         {
1625           if (collect == &stepping_list)        /* end stepping actions */
1626             collect = &tracepoint_list;
1627           else
1628             break;                      /* end tracepoint actions */
1629         }
1630     }                   /* for */
1631   memrange_sortmerge (&tracepoint_list); 
1632   memrange_sortmerge (&stepping_list); 
1633
1634   *tdp_actions      = stringify_collection_list (&tracepoint_list, &tdp_buff);
1635   *stepping_actions = stringify_collection_list (&stepping_list,   &step_buff);
1636 }
1637
1638 static void
1639 add_aexpr(collect, aexpr)
1640      struct collection_list *collect;
1641      struct agent_expr *aexpr;
1642 {
1643   if (collect->next_aexpr_elt >= collect->aexpr_listsize)
1644     {
1645       collect->aexpr_list =
1646         xrealloc (collect->aexpr_list,
1647                   2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
1648       collect->aexpr_listsize *= 2;
1649     }
1650   collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
1651   collect->next_aexpr_elt++;
1652 }
1653
1654 static char target_buf[2048];
1655
1656 /* Set "transparent" memory ranges
1657
1658    Allow trace mechanism to treat text-like sections
1659    (and perhaps all read-only sections) transparently, 
1660    i.e. don't reject memory requests from these address ranges
1661    just because they haven't been collected.  */
1662
1663 static void
1664 remote_set_transparent_ranges (void)
1665 {
1666   extern bfd *exec_bfd;
1667   asection *s;
1668   bfd_size_type size;
1669   bfd_vma lma;
1670   int anysecs = 0;
1671
1672   if (!exec_bfd)
1673     return;             /* no information to give. */
1674
1675   strcpy (target_buf, "QTro");
1676   for (s = exec_bfd->sections; s; s = s->next)
1677     {
1678       char tmp[40];
1679
1680       if ((s->flags & SEC_LOAD)     == 0 ||
1681        /* (s->flags & SEC_CODE)     == 0 || */
1682           (s->flags & SEC_READONLY) == 0)
1683         continue;
1684
1685       anysecs = 1;
1686       lma  = s->lma;
1687       size = bfd_get_section_size_before_reloc (s);
1688       sprintf (tmp, ":%x,%x", lma, lma + size);
1689       strcat (target_buf, tmp);
1690     }
1691   if (anysecs)
1692     {
1693       putpkt (target_buf);
1694       getpkt (target_buf, 0);
1695     }
1696 }
1697
1698 /* tstart command:
1699  
1700    Tell target to clear any previous trace experiment.
1701    Walk the list of tracepoints, and send them (and their actions)
1702    to the target.  If no errors, 
1703    Tell target to start a new trace experiment.  */
1704
1705 static void
1706 trace_start_command (args, from_tty)
1707      char *args;
1708      int from_tty;
1709 { /* STUB_COMM MOSTLY_IMPLEMENTED */
1710   struct tracepoint *t;
1711   char buf[2048];
1712   char **tdp_actions;
1713   char **stepping_actions;
1714   int ndx;
1715   struct cleanup *old_chain = NULL;
1716
1717   dont_repeat ();       /* like "run", dangerous to repeat accidentally */
1718   
1719   if (target_is_remote ())
1720     {
1721       putpkt ("QTinit");
1722       remote_get_noisy_reply (target_buf);
1723       if (strcmp (target_buf, "OK"))
1724         error ("Target does not support this command.");
1725
1726       ALL_TRACEPOINTS (t)
1727         {
1728           int ss_count;         /* if actions include singlestepping */
1729           int disable_mask;     /* ??? */
1730           int enable_mask;      /* ??? */
1731
1732           sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address, 
1733                    t->enabled == enabled ? 'E' : 'D', 
1734                    t->step_count, t->pass_count);
1735
1736           if (t->actions)
1737             strcat (buf, "-");
1738           putpkt (buf);
1739           remote_get_noisy_reply (target_buf);
1740           if (strcmp (target_buf, "OK"))
1741             error ("Target does not support tracepoints.");
1742
1743           if (t->actions)
1744             {
1745               encode_actions (t, &tdp_actions, &stepping_actions);
1746               old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
1747                                         tdp_actions);
1748               (void) make_cleanup (free_actions_list_cleanup_wrapper,
1749                                    stepping_actions);
1750
1751               /* do_single_steps (t); */
1752               if (tdp_actions)
1753                 {
1754                   for (ndx = 0; tdp_actions[ndx]; ndx++)
1755                     {
1756                       QUIT;             /* allow user to bail out with ^C */
1757                       sprintf (buf, "QTDP:-%x:%x:%s%c",
1758                                t->number, t->address,
1759                                tdp_actions[ndx],
1760                                ((tdp_actions[ndx+1] || stepping_actions)
1761                                 ? '-' : 0));
1762                       putpkt (buf);
1763                       remote_get_noisy_reply (target_buf);
1764                       if (strcmp (target_buf, "OK"))
1765                         error ("Error on target while setting tracepoints.");
1766                     }
1767                 }
1768               if (stepping_actions)
1769                 {
1770                   for (ndx = 0; stepping_actions[ndx]; ndx++)
1771                     {
1772                       QUIT;             /* allow user to bail out with ^C */
1773                       sprintf (buf, "QTDP:-%x:%x:%s%s%s",
1774                                t->number, t->address,
1775                                ((ndx == 0) ? "S" : ""),
1776                                stepping_actions[ndx],
1777                                (stepping_actions[ndx+1] ? "-" : ""));
1778                       putpkt (buf);
1779                       remote_get_noisy_reply (target_buf);
1780                       if (strcmp (target_buf, "OK"))
1781                         error ("Error on target while setting tracepoints.");
1782                     }
1783                 }
1784
1785               do_cleanups (old_chain);
1786             }
1787         }
1788       /* Tell target to treat text-like sections as transparent */
1789       remote_set_transparent_ranges ();
1790       /* Now insert traps and begin collecting data */
1791       putpkt ("QTStart");
1792       remote_get_noisy_reply (target_buf);
1793       if (strcmp (target_buf, "OK"))
1794         error ("Bogus reply from target: %s", target_buf);
1795       set_traceframe_num (-1);  /* all old traceframes invalidated */
1796       set_tracepoint_num (-1);
1797       set_traceframe_context(-1);
1798       trace_running_p = 1;
1799       if (trace_start_stop_hook)
1800         trace_start_stop_hook(1, from_tty);
1801       
1802     }
1803   else
1804     error ("Trace can only be run on remote targets.");
1805 }
1806
1807 /* tstop command */
1808 static void
1809 trace_stop_command (args, from_tty)
1810      char *args;
1811      int from_tty;
1812 { /* STUB_COMM IS_IMPLEMENTED */
1813   if (target_is_remote ())
1814     {
1815       putpkt ("QTStop");
1816       remote_get_noisy_reply (target_buf);
1817       if (strcmp (target_buf, "OK"))
1818         error ("Bogus reply from target: %s", target_buf);
1819       trace_running_p = 0;
1820       if (trace_start_stop_hook)
1821         trace_start_stop_hook(0, from_tty);
1822     }
1823   else
1824     error ("Trace can only be run on remote targets.");
1825 }
1826
1827 unsigned long trace_running_p;
1828
1829 /* tstatus command */
1830 static void
1831 trace_status_command (args, from_tty)
1832      char *args;
1833      int from_tty;
1834 { /* STUB_COMM IS_IMPLEMENTED */
1835   if (target_is_remote ())
1836     {
1837       putpkt ("qTStatus");
1838       remote_get_noisy_reply (target_buf);
1839
1840       if (target_buf[0] != 'T' ||
1841           (target_buf[1] != '0' && target_buf[1] != '1'))
1842         error ("Bogus reply from target: %s", target_buf);
1843
1844       /* exported for use by the GUI */
1845       trace_running_p = (target_buf[1] == '1');
1846     }
1847   else
1848     error ("Trace can only be run on remote targets.");
1849 }
1850
1851 /* Worker function for the various flavors of the tfind command */
1852 static void
1853 finish_tfind_command (msg, from_tty)
1854      char *msg;
1855      int from_tty;
1856 {
1857   int target_frameno = -1, target_tracept = -1;
1858   CORE_ADDR old_frame_addr;
1859   struct symbol *old_func;
1860   char *reply;
1861
1862   old_frame_addr = FRAME_FP (get_current_frame ());
1863   old_func       = find_pc_function (read_pc ());
1864
1865   putpkt (msg);
1866   reply = remote_get_noisy_reply (msg);
1867
1868   while (reply && *reply)
1869     switch (*reply) {
1870     case 'F':
1871       if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
1872         { 
1873           /* A request for a non-existant trace frame has failed.
1874              Our response will be different, depending on FROM_TTY:
1875
1876              If FROM_TTY is true, meaning that this command was 
1877              typed interactively by the user, then give an error
1878              and DO NOT change the state of traceframe_number etc.
1879
1880              However if FROM_TTY is false, meaning that we're either
1881              in a script, a loop, or a user-defined command, then 
1882              DON'T give an error, but DO change the state of
1883              traceframe_number etc. to invalid.
1884
1885              The rationalle is that if you typed the command, you
1886              might just have committed a typo or something, and you'd
1887              like to NOT lose your current debugging state.  However
1888              if you're in a user-defined command or especially in a
1889              loop, then you need a way to detect that the command
1890              failed WITHOUT aborting.  This allows you to write
1891              scripts that search thru the trace buffer until the end,
1892              and then continue on to do something else.  */
1893
1894           if (from_tty)
1895             error ("Target failed to find requested trace frame.");
1896           else
1897             {
1898               if (info_verbose)
1899                 printf_filtered ("End of trace buffer.\n");
1900               /* The following will not recurse, since it's special-cased */
1901               trace_find_command ("-1", from_tty);
1902               reply = NULL;     /* break out of loop, 
1903                                    (avoid recursive nonsense) */
1904             }
1905         }
1906       break;
1907     case 'T':
1908       if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
1909         error ("Target failed to find requested trace frame.");
1910       break;
1911     case 'O':   /* "OK"? */
1912       if (reply[1] == 'K' && reply[2] == '\0')
1913         reply += 2;
1914       else
1915         error ("Bogus reply from target: %s", reply);
1916       break;
1917     default:
1918       error ("Bogus reply from target: %s", reply);
1919     }
1920
1921   flush_cached_frames ();
1922   registers_changed ();
1923   select_frame (get_current_frame (), 0);
1924   set_traceframe_num (target_frameno);
1925   set_tracepoint_num (target_tracept);
1926   if (target_frameno == -1)
1927     set_traceframe_context (-1);
1928   else
1929     set_traceframe_context (read_pc ());
1930
1931   if (from_tty)
1932     {
1933       int source_only;
1934
1935       /* NOTE: in immitation of the step command, try to determine
1936          whether we have made a transition from one function to another.
1937          If so, we'll print the "stack frame" (ie. the new function and
1938          it's arguments) -- otherwise we'll just show the new source line.
1939
1940          This determination is made by checking (1) whether the current
1941          function has changed, and (2) whether the current FP has changed.
1942          Hack: if the FP wasn't collected, either at the current or the
1943          previous frame, assume that the FP has NOT changed.  */
1944
1945       if (old_func       == find_pc_function (read_pc ()) &&
1946          (old_frame_addr == 0 ||
1947           FRAME_FP (get_current_frame ()) == 0 ||
1948           old_frame_addr == FRAME_FP (get_current_frame ())))
1949         source_only = -1;
1950       else
1951         source_only =  1;
1952
1953       print_stack_frame (selected_frame, selected_frame_level, source_only);
1954       do_displays ();
1955     }
1956 }
1957
1958 /* trace_find_command takes a trace frame number n, 
1959    sends "QTFrame:<n>" to the target, 
1960    and accepts a reply that may contain several optional pieces
1961    of information: a frame number, a tracepoint number, and an
1962    indication of whether this is a trap frame or a stepping frame.
1963
1964    The minimal response is just "OK" (which indicates that the 
1965    target does not give us a frame number or a tracepoint number).
1966    Instead of that, the target may send us a string containing
1967    any combination of:
1968         F<hexnum>       (gives the selected frame number)
1969         T<hexnum>       (gives the selected tracepoint number)
1970    */
1971
1972 /* tfind command */
1973 static void
1974 trace_find_command (args, from_tty)
1975      char *args;
1976      int from_tty;
1977 { /* STUB_COMM PART_IMPLEMENTED */
1978   /* this should only be called with a numeric argument */
1979   int frameno = -1;
1980   char *tmp;
1981
1982   if (target_is_remote ())
1983     {
1984       if (trace_find_hook)
1985         trace_find_hook (args, from_tty);  
1986       
1987       if (args == 0 || *args == 0)
1988         { /* TFIND with no args means find NEXT trace frame. */
1989           if (traceframe_number == -1)
1990             frameno = 0;        /* "next" is first one */
1991           else
1992             frameno = traceframe_number + 1;
1993         }
1994       else if (0 == strcmp (args, "-"))
1995         {
1996           if (traceframe_number == -1)
1997             error ("not debugging trace buffer");
1998           else if (from_tty && traceframe_number == 0)
1999             error ("already at start of trace buffer");
2000
2001           frameno = traceframe_number - 1;
2002         }
2003       else
2004         frameno = parse_and_eval_address (args);
2005
2006       if (frameno < -1)
2007         error ("invalid input (%d is less than zero)", frameno);
2008
2009       sprintf (target_buf, "QTFrame:%x", frameno);
2010       finish_tfind_command (target_buf, from_tty);
2011     }
2012   else
2013     error ("Trace can only be run on remote targets.");
2014 }
2015
2016 /* tfind end */
2017 static void
2018 trace_find_end_command (args, from_tty)
2019      char *args;
2020      int from_tty;
2021 {
2022   trace_find_command ("-1", from_tty);
2023 }
2024
2025 /* tfind none */
2026 static void
2027 trace_find_none_command (args, from_tty)
2028      char *args;
2029      int from_tty;
2030 {
2031   trace_find_command ("-1", from_tty);
2032 }
2033
2034 /* tfind start */
2035 static void
2036 trace_find_start_command (args, from_tty)
2037      char *args;
2038      int from_tty;
2039 {
2040   trace_find_command ("0", from_tty);
2041 }
2042
2043 /* tfind pc command */
2044 static void
2045 trace_find_pc_command (args, from_tty)
2046      char *args;
2047      int from_tty;
2048 { /* STUB_COMM PART_IMPLEMENTED */
2049   CORE_ADDR pc;
2050   char *tmp;
2051
2052   if (target_is_remote ())
2053     {
2054       if (args == 0 || *args == 0)
2055         pc = read_pc ();        /* default is current pc */
2056       else
2057         pc = parse_and_eval_address (args);
2058
2059       sprintf (target_buf, "QTFrame:pc:%x", pc);
2060       finish_tfind_command (target_buf, from_tty);
2061     }
2062   else
2063     error ("Trace can only be run on remote targets.");
2064 }
2065
2066 /* tfind tracepoint command */
2067 static void
2068 trace_find_tracepoint_command (args, from_tty)
2069      char *args;
2070      int from_tty;
2071 { /* STUB_COMM PART_IMPLEMENTED */
2072   int tdp;
2073   char buf[40], *tmp;
2074
2075   if (target_is_remote ())
2076     {
2077       if (args == 0 || *args == 0)
2078         if (tracepoint_number == -1)
2079           error ("No current tracepoint -- please supply an argument.");
2080         else
2081           tdp = tracepoint_number;      /* default is current TDP */
2082       else
2083         tdp = parse_and_eval_address (args);
2084
2085       sprintf (target_buf, "QTFrame:tdp:%x", tdp);
2086       finish_tfind_command (target_buf, from_tty);
2087     }
2088   else
2089     error ("Trace can only be run on remote targets.");
2090 }
2091
2092 /* TFIND LINE command:
2093  
2094    This command will take a sourceline for argument, just like BREAK
2095    or TRACE (ie. anything that "decode_line_1" can handle).  
2096    
2097    With no argument, this command will find the next trace frame 
2098    corresponding to a source line OTHER THAN THE CURRENT ONE.  */
2099
2100 static void
2101 trace_find_line_command (args, from_tty)
2102      char *args;
2103      int from_tty;
2104 { /* STUB_COMM PART_IMPLEMENTED */
2105   static CORE_ADDR start_pc, end_pc;
2106   struct symtabs_and_lines sals;
2107   struct symtab_and_line sal;
2108   char *tmp;
2109   struct cleanup *old_chain;
2110
2111   if (target_is_remote ())
2112     {
2113       if (args == 0 || *args == 0)
2114         {
2115           sal = find_pc_line ((get_current_frame ())->pc, 0);
2116           sals.nelts = 1;
2117           sals.sals = (struct symtab_and_line *)
2118             xmalloc (sizeof (struct symtab_and_line));
2119           sals.sals[0] = sal;
2120         }
2121       else
2122         {
2123           sals = decode_line_spec (args, 1);
2124           sal  = sals.sals[0];
2125         }
2126
2127       old_chain = make_cleanup (free, sals.sals);
2128       if (sal.symtab == 0)
2129         {
2130           printf_filtered ("TFIND: No line number information available");
2131           if (sal.pc != 0)
2132             {
2133               /* This is useful for "info line *0x7f34".  If we can't tell the
2134                  user about a source line, at least let them have the symbolic
2135                  address.  */
2136               printf_filtered (" for address ");
2137               wrap_here ("  ");
2138               print_address (sal.pc, gdb_stdout);
2139               printf_filtered (";\n -- will attempt to find by PC. \n");
2140             }
2141           else
2142             {
2143               printf_filtered (".\n");
2144               return;   /* no line, no PC; what can we do? */
2145             }
2146         }
2147       else if (sal.line > 0
2148                && find_line_pc_range (sal, &start_pc, &end_pc))
2149         {
2150           if (start_pc == end_pc)
2151             {
2152               printf_filtered ("Line %d of \"%s\"",
2153                                sal.line, sal.symtab->filename);
2154               wrap_here ("  ");
2155               printf_filtered (" is at address ");
2156               print_address (start_pc, gdb_stdout);
2157               wrap_here ("  ");
2158               printf_filtered (" but contains no code.\n");
2159               sal = find_pc_line (start_pc, 0);
2160               if (sal.line > 0 &&
2161                   find_line_pc_range (sal, &start_pc, &end_pc) &&
2162                   start_pc != end_pc)
2163                 printf_filtered ("Attempting to find line %d instead.\n",
2164                                  sal.line);
2165               else
2166                 error ("Cannot find a good line.");
2167             }
2168         }
2169       else
2170         /* Is there any case in which we get here, and have an address
2171            which the user would want to see?  If we have debugging symbols
2172            and no line numbers?  */
2173         error ("Line number %d is out of range for \"%s\".\n",
2174                sal.line, sal.symtab->filename);
2175
2176       if (args && *args)        /* find within range of stated line */
2177         sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
2178       else                      /* find OUTSIDE OF range of CURRENT line */
2179         sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
2180       finish_tfind_command (target_buf, from_tty);
2181       do_cleanups (old_chain);
2182     }
2183   else
2184       error ("Trace can only be run on remote targets.");
2185 }
2186
2187 /* tfind range command */
2188 static void
2189 trace_find_range_command (args, from_tty)
2190      char *args;
2191      int from_tty;
2192 { /* STUB_COMM PART_IMPLEMENTED */
2193   static CORE_ADDR start, stop;
2194   char *tmp;
2195
2196   if (target_is_remote ())
2197     {
2198       if (args == 0 || *args == 0)
2199         { /* XXX FIXME: what should default behavior be? */
2200           printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
2201           return;
2202         }
2203
2204       if (0 != (tmp = strchr (args, ',' )))
2205         {
2206           *tmp++ = '\0';        /* terminate start address */
2207           while (isspace (*tmp))
2208             tmp++;
2209           start = parse_and_eval_address (args);
2210           stop  = parse_and_eval_address (tmp);
2211         }
2212       else
2213         { /* no explicit end address? */
2214           start = parse_and_eval_address (args);
2215           stop  = start + 1; /* ??? */
2216         }
2217
2218       sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
2219       finish_tfind_command (target_buf, from_tty);
2220     }
2221   else
2222       error ("Trace can only be run on remote targets.");
2223 }
2224
2225 /* tfind outside command */
2226 static void
2227 trace_find_outside_command (args, from_tty)
2228      char *args;
2229      int from_tty;
2230 { /* STUB_COMM PART_IMPLEMENTED */
2231   CORE_ADDR start, stop;
2232   char *tmp;
2233
2234   if (target_is_remote ())
2235     {
2236       if (args == 0 || *args == 0)
2237         { /* XXX FIXME: what should default behavior be? */
2238           printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
2239           return;
2240         }
2241
2242       if (0 != (tmp = strchr (args, ',' )))
2243         {
2244           *tmp++ = '\0';        /* terminate start address */
2245           while (isspace (*tmp))
2246             tmp++;
2247           start = parse_and_eval_address (args);
2248           stop  = parse_and_eval_address (tmp);
2249         }
2250       else
2251         { /* no explicit end address? */
2252           start = parse_and_eval_address (args);
2253           stop  = start + 1; /* ??? */
2254         }
2255
2256       sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
2257       finish_tfind_command (target_buf, from_tty);
2258     }
2259   else
2260       error ("Trace can only be run on remote targets.");
2261 }
2262
2263 /* save-tracepoints command */
2264 static void
2265 tracepoint_save_command (args, from_tty)
2266      char *args;
2267      int from_tty;
2268 {
2269   struct tracepoint  *tp;
2270   struct action_line *line;
2271   FILE *fp;
2272   char *i1 = "    ", *i2 = "      ";
2273   char *indent, *actionline;
2274
2275   if (args == 0 || *args == 0)
2276     error ("Argument required (file name in which to save tracepoints");
2277
2278   if (tracepoint_chain == 0)
2279     {
2280       warning ("save-tracepoints: no tracepoints to save.\n");
2281       return;
2282     }
2283
2284   if (!(fp = fopen (args, "w")))
2285     error ("Unable to open file '%s' for saving tracepoints");
2286
2287   ALL_TRACEPOINTS (tp)
2288     {
2289       if (tp->addr_string)
2290         fprintf (fp, "trace %s\n", tp->addr_string);
2291       else
2292         fprintf (fp, "trace *0x%x\n", tp->address);
2293
2294       if (tp->pass_count)
2295         fprintf (fp, "  passcount %d\n", tp->pass_count);
2296
2297       if (tp->actions)
2298         {
2299           fprintf (fp, "  actions\n");
2300           indent = i1;
2301           for (line = tp->actions; line; line = line->next)
2302             {
2303               struct cmd_list_element *cmd;
2304
2305               QUIT;                     /* allow user to bail out with ^C */
2306               actionline = line->action;
2307               while (isspace(*actionline))
2308                 actionline++;
2309
2310               fprintf (fp, "%s%s\n", indent, actionline);
2311               if (*actionline != '#')   /* skip for comment lines */
2312                 {
2313                   cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
2314                   if (cmd == 0)
2315                     error ("Bad action list item: %s", actionline);
2316                   if (cmd->function.cfunc == while_stepping_pseudocommand)
2317                     indent = i2;
2318                   else if (cmd->function.cfunc == end_actions_pseudocommand)
2319                     indent = i1;
2320                 }
2321             }
2322         }
2323     }
2324   fclose (fp);
2325   if (from_tty)
2326     printf_filtered ("Tracepoints saved to file '%s'.\n", args);
2327   return;
2328 }
2329
2330 /* info scope command: list the locals for a scope.  */
2331 static void
2332 scope_info (args, from_tty)
2333      char *args;
2334      int from_tty;
2335 {
2336   struct symtab_and_line sal;
2337   struct symtabs_and_lines sals;
2338   struct symbol *sym;
2339   struct minimal_symbol *msym;
2340   struct block *block;
2341   char **canonical, *symname, *save_args = args;
2342   int i, j, nsyms, count = 0;
2343
2344   if (args == 0 || *args == 0)
2345     error ("requires an argument (function, line or *addr) to define a scope");
2346
2347   sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2348   if (sals.nelts == 0)
2349     return;             /* presumably decode_line_1 has already warned */
2350
2351   /* Resolve line numbers to PC */
2352   resolve_sal_pc (&sals.sals[0]);
2353   block = block_for_pc (sals.sals[0].pc);
2354
2355   while (block != 0)
2356     {
2357       QUIT;                             /* allow user to bail out with ^C */
2358       nsyms = BLOCK_NSYMS (block);
2359       for (i = 0; i < nsyms; i++)
2360         {
2361           QUIT;                         /* allow user to bail out with ^C */
2362           if (count == 0)
2363             printf_filtered ("Scope for %s:\n", save_args);
2364           count++;
2365           sym = BLOCK_SYM (block, i);
2366           symname = SYMBOL_NAME (sym);
2367           if (symname == NULL || *symname == '\0')
2368             continue;   /* probably botched, certainly useless */
2369
2370           printf_filtered ("Symbol %s is ", symname);
2371           switch (SYMBOL_CLASS (sym)) {
2372           default:
2373           case LOC_UNDEF:               /* messed up symbol? */
2374             printf_filtered ("a bogus symbol, class %d.\n", 
2375                              SYMBOL_CLASS (sym));
2376             count--;                    /* don't count this one */
2377             continue;
2378           case LOC_CONST:
2379             printf_filtered ("a constant with value %d (0x%x)", 
2380                              SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
2381             break;
2382           case LOC_CONST_BYTES:
2383             printf_filtered ("constant bytes: ");
2384             if (SYMBOL_TYPE (sym))
2385               for (j = 0; j < TYPE_LENGTH (SYMBOL_TYPE (sym)); j++)
2386                 fprintf_filtered (gdb_stdout, " %02x",
2387                                   (unsigned) SYMBOL_VALUE_BYTES (sym) [j]);
2388             break;
2389           case LOC_STATIC:
2390             printf_filtered ("in static storage at address ");
2391             print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2392             break;
2393           case LOC_REGISTER:
2394             printf_filtered ("a local variable in register $%s",
2395                              REGISTER_NAME (SYMBOL_VALUE (sym)));
2396             break;
2397           case LOC_ARG:
2398           case LOC_LOCAL_ARG:
2399             printf_filtered ("an argument at stack/frame offset %ld",
2400                              SYMBOL_VALUE (sym));
2401             break;
2402           case LOC_LOCAL:
2403             printf_filtered ("a local variable at frame offset %ld",
2404                              SYMBOL_VALUE (sym));
2405             break;
2406           case LOC_REF_ARG:
2407             printf_filtered ("a reference argument at offset %ld",
2408                              SYMBOL_VALUE (sym));
2409             break;
2410           case LOC_REGPARM:
2411             printf_filtered ("an argument in register $%s",
2412                              REGISTER_NAME (SYMBOL_VALUE (sym)));
2413             break;
2414           case LOC_REGPARM_ADDR:
2415             printf_filtered ("the address of an argument, in register $%s",
2416                              REGISTER_NAME (SYMBOL_VALUE (sym)));
2417             break;
2418           case LOC_TYPEDEF:
2419             printf_filtered ("a typedef.\n");
2420             continue;
2421           case LOC_LABEL:
2422             printf_filtered ("a label at address ");
2423             print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2424             break;
2425           case LOC_BLOCK:
2426             printf_filtered ("a function at address ");
2427             print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
2428                                    gdb_stdout);
2429             break;
2430           case LOC_BASEREG:
2431             printf_filtered ("a variable at offset %d from register $%s",
2432                              SYMBOL_VALUE (sym),
2433                              REGISTER_NAME  (SYMBOL_BASEREG (sym)));
2434             break;
2435           case LOC_BASEREG_ARG:
2436             printf_filtered ("an argument at offset %d from register $%s",
2437                              SYMBOL_VALUE (sym),
2438                              REGISTER_NAME  (SYMBOL_BASEREG (sym)));
2439             break;
2440           case LOC_UNRESOLVED:
2441             msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
2442             if (msym == NULL)
2443               printf_filtered ("Unresolved Static");
2444             else
2445               {
2446                 printf_filtered ("static storage at address ");
2447                 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1, 
2448                                        gdb_stdout);
2449               }
2450             break;
2451           case LOC_OPTIMIZED_OUT:
2452             printf_filtered ("optimized out.\n");
2453             continue;
2454           }
2455           if (SYMBOL_TYPE (sym))
2456             printf_filtered (", length %d.\n", 
2457                              TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
2458         }
2459       if (BLOCK_FUNCTION (block))
2460         break;
2461       else
2462         block = BLOCK_SUPERBLOCK (block);
2463     }
2464   if (count <= 0)
2465     printf_filtered ("Scope for %s contains no locals or arguments.\n",
2466                      save_args);
2467 }
2468
2469 /* worker function (cleanup) */
2470 static void
2471 replace_comma (comma)
2472      char *comma;
2473 {
2474   *comma = ',';
2475 }
2476
2477 /* tdump command */
2478 static void
2479 trace_dump_command (args, from_tty)
2480      char *args;
2481      int from_tty;
2482 {
2483   struct tracepoint  *t;
2484   struct action_line *action;
2485   char               *action_exp, *next_comma;
2486   struct cleanup     *old_cleanups;
2487   int                 stepping_actions = 0;
2488   int                 stepping_frame   = 0;
2489
2490   if (!target_is_remote ())
2491     {
2492       error ("Trace can only be run on remote targets.");
2493       return;
2494     }
2495
2496   if (tracepoint_number == -1)
2497     {
2498       warning ("No current trace frame.");
2499       return;
2500     }
2501
2502   ALL_TRACEPOINTS (t)
2503     if (t->number == tracepoint_number)
2504       break;
2505
2506   if (t == NULL)
2507     error ("No known tracepoint matches 'current' tracepoint #%d.", 
2508            tracepoint_number);
2509
2510   old_cleanups = make_cleanup (null_cleanup, NULL);
2511
2512   printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n", 
2513                    tracepoint_number, traceframe_number);
2514
2515   /* The current frame is a trap frame if the frame PC is equal
2516      to the tracepoint PC.  If not, then the current frame was
2517      collected during single-stepping.  */
2518
2519   stepping_frame = (t->address != read_pc());
2520
2521   for (action = t->actions; action; action = action->next)
2522     {
2523       struct cmd_list_element *cmd;
2524
2525       QUIT;                             /* allow user to bail out with ^C */
2526       action_exp = action->action;
2527       while (isspace (*action_exp))
2528         action_exp++;
2529
2530       /* The collection actions to be done while stepping are
2531          bracketed by the commands "while-stepping" and "end".  */
2532
2533       if (*action_exp == '#')   /* comment line */
2534         continue;
2535
2536       cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
2537       if (cmd == 0)
2538         error ("Bad action list item: %s", action_exp);
2539
2540       if (cmd->function.cfunc == while_stepping_pseudocommand)
2541         stepping_actions = 1;
2542       else if (cmd->function.cfunc == end_actions_pseudocommand)
2543         stepping_actions = 0;
2544       else if (cmd->function.cfunc == collect_pseudocommand)
2545         {
2546           /* Display the collected data.
2547              For the trap frame, display only what was collected at the trap.
2548              Likewise for stepping frames, display only what was collected
2549              while stepping.  This means that the two boolean variables,
2550              STEPPING_FRAME and STEPPING_ACTIONS should be equal.  */
2551           if (stepping_frame == stepping_actions)
2552             {
2553               do { /* repeat over a comma-separated list */
2554                 QUIT;           /* allow user to bail out with ^C */
2555                 if (*action_exp == ',')
2556                   action_exp++;
2557                 while (isspace (*action_exp))
2558                   action_exp++;
2559
2560                 next_comma = strchr (action_exp, ',');
2561
2562                 if      (0 == strncasecmp (action_exp, "$reg", 4))
2563                   registers_info (NULL, from_tty);
2564                 else if (0 == strncasecmp (action_exp, "$loc", 4))
2565                   locals_info (NULL, from_tty);
2566                 else if (0 == strncasecmp (action_exp, "$arg", 4))
2567                   args_info (NULL, from_tty);
2568                 else
2569                   { /* variable */
2570                     if (next_comma)
2571                       {
2572                         make_cleanup (replace_comma, next_comma);
2573                         *next_comma = '\0';
2574                       }
2575                     printf_filtered ("%s = ", action_exp);
2576                     output_command (action_exp, from_tty);
2577                     printf_filtered ("\n");
2578                   }
2579                 if (next_comma)
2580                   *next_comma = ',';
2581                 action_exp = next_comma;
2582               } while (action_exp && *action_exp == ',');
2583             }
2584         }
2585     }
2586   discard_cleanups (old_cleanups);
2587 }
2588
2589 /* Convert the memory pointed to by mem into hex, placing result in buf.
2590  * Return a pointer to the last char put in buf (null)
2591  * "stolen" from sparc-stub.c
2592  */
2593
2594 static const char hexchars[]="0123456789abcdef";
2595
2596 static unsigned char *
2597 mem2hex(mem, buf, count)
2598      unsigned char *mem;
2599      unsigned char *buf;
2600      int count;
2601 {
2602   unsigned char ch;
2603
2604   while (count-- > 0)
2605     {
2606       ch = *mem++;
2607
2608       *buf++ = hexchars[ch >> 4];
2609       *buf++ = hexchars[ch & 0xf];
2610     }
2611
2612   *buf = 0;
2613
2614   return buf;
2615 }
2616
2617 int get_traceframe_number()
2618 {
2619  return traceframe_number;
2620 }
2621
2622
2623 /* module initialization */
2624 void
2625 _initialize_tracepoint ()
2626 {
2627   tracepoint_chain  = 0;
2628   tracepoint_count  = 0;
2629   traceframe_number = -1;
2630   tracepoint_number = -1;
2631
2632   set_internalvar (lookup_internalvar ("tpnum"), 
2633                    value_from_longest (builtin_type_int, (LONGEST) 0));
2634   set_internalvar (lookup_internalvar ("trace_frame"), 
2635                    value_from_longest (builtin_type_int, (LONGEST) -1));
2636
2637   if (tracepoint_list.list == NULL)
2638     {
2639       tracepoint_list.listsize = 128;
2640       tracepoint_list.list = xmalloc 
2641         (tracepoint_list.listsize * sizeof (struct memrange));
2642     }
2643   if (tracepoint_list.aexpr_list == NULL)
2644     {
2645       tracepoint_list.aexpr_listsize = 128;
2646       tracepoint_list.aexpr_list = xmalloc
2647         (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *));
2648     }
2649
2650   if (stepping_list.list == NULL)
2651     {
2652       stepping_list.listsize = 128;
2653       stepping_list.list = xmalloc 
2654         (stepping_list.listsize * sizeof (struct memrange));
2655     }
2656
2657   if (stepping_list.aexpr_list == NULL)
2658     {
2659       stepping_list.aexpr_listsize = 128;
2660       stepping_list.aexpr_list = xmalloc
2661         (stepping_list.aexpr_listsize * sizeof (struct agent_expr *));
2662     }
2663
2664   add_info ("scope", scope_info, 
2665             "List the variables local to a scope");
2666
2667   add_cmd ("tracepoints", class_trace, NO_FUNCTION, 
2668            "Tracing of program execution without stopping the program.", 
2669            &cmdlist);
2670
2671   add_info ("tracepoints", tracepoints_info,
2672             "Status of tracepoints, or tracepoint number NUMBER.\n\
2673 Convenience variable \"$tpnum\" contains the number of the\n\
2674 last tracepoint set.");
2675
2676   add_info_alias ("tp", "tracepoints", 1);
2677
2678   add_com ("save-tracepoints", class_trace, tracepoint_save_command, 
2679            "Save current tracepoint definitions as a script.\n\
2680 Use the 'source' command in another debug session to restore them.");
2681
2682   add_com ("tdump", class_trace, trace_dump_command, 
2683            "Print everything collected at the current tracepoint.");
2684
2685   add_prefix_cmd ("tfind",  class_trace, trace_find_command,
2686                   "Select a trace frame;\n\
2687 No argument means forward by one frame; '-' meand backward by one frame.",
2688                   &tfindlist, "tfind ", 1, &cmdlist);
2689
2690   add_cmd ("outside", class_trace, trace_find_outside_command,
2691            "Select a trace frame whose PC is outside the given \
2692 range.\nUsage: tfind outside addr1, addr2", 
2693            &tfindlist);
2694
2695   add_cmd ("range", class_trace, trace_find_range_command,
2696            "Select a trace frame whose PC is in the given range.\n\
2697 Usage: tfind range addr1,addr2", 
2698            &tfindlist);
2699
2700   add_cmd ("line", class_trace, trace_find_line_command,
2701            "Select a trace frame by source line.\n\
2702 Argument can be a line number (with optional source file), \n\
2703 a function name, or '*' followed by an address.\n\
2704 Default argument is 'the next source line that was traced'.",
2705            &tfindlist);
2706
2707   add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
2708            "Select a trace frame by tracepoint number.\n\
2709 Default is the tracepoint for the current trace frame.",
2710            &tfindlist);
2711
2712   add_cmd ("pc", class_trace, trace_find_pc_command,
2713            "Select a trace frame by PC.\n\
2714 Default is the current PC, or the PC of the current trace frame.",
2715            &tfindlist);
2716
2717   add_cmd ("end", class_trace, trace_find_end_command,
2718            "Synonym for 'none'.\n\
2719 De-select any trace frame and resume 'live' debugging.",
2720            &tfindlist);
2721
2722   add_cmd ("none", class_trace, trace_find_none_command,
2723            "De-select any trace frame and resume 'live' debugging.",
2724            &tfindlist);
2725
2726   add_cmd ("start", class_trace, trace_find_start_command,
2727            "Select the first trace frame in the trace buffer.",
2728            &tfindlist);
2729
2730   add_com ("tstatus",  class_trace, trace_status_command,
2731            "Display the status of the current trace data collection.");
2732
2733   add_com ("tstop",  class_trace, trace_stop_command,
2734            "Stop trace data collection.");
2735
2736   add_com ("tstart", class_trace, trace_start_command,
2737            "Start trace data collection.");
2738
2739   add_com ("passcount", class_trace, trace_pass_command, 
2740            "Set the passcount for a tracepoint.\n\
2741 The trace will end when the tracepoint has been passed 'count' times.\n\
2742 Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2743 if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2744
2745   add_com ("end", class_trace, end_actions_pseudocommand,
2746            "Ends a list of commands or actions.\n\
2747 Several GDB commands allow you to enter a list of commands or actions.\n\
2748 Entering \"end\" on a line by itself is the normal way to terminate\n\
2749 such a list.\n\n\
2750 Note: the \"end\" command cannot be used at the gdb prompt.");
2751
2752   add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
2753            "Specify single-stepping behavior at a tracepoint.\n\
2754 Argument is number of instructions to trace in single-step mode\n\
2755 following the tracepoint.  This command is normally followed by\n\
2756 one or more \"collect\" commands, to specify what to collect\n\
2757 while single-stepping.\n\n\
2758 Note: this command can only be used in a tracepoint \"actions\" list.");
2759
2760   add_com_alias ("ws",         "while-stepping", class_alias, 0);
2761   add_com_alias ("stepping",   "while-stepping", class_alias, 0);
2762
2763   add_com ("collect", class_trace, collect_pseudocommand, 
2764            "Specify one or more data items to be collected at a tracepoint.\n\
2765 Accepts a comma-separated list of (one or more) expressions.  GDB will\n\
2766 collect all data (variables, registers) referenced by that expression.\n\
2767 Also accepts the following special arguments:\n\
2768     $regs   -- all registers.\n\
2769     $args   -- all function arguments.\n\
2770     $locals -- all variables local to the block/function scope.\n\
2771 Note: this command can only be used in a tracepoint \"actions\" list.");
2772
2773   add_com ("actions", class_trace, trace_actions_command,
2774            "Specify the actions to be taken at a tracepoint.\n\
2775 Tracepoint actions may include collecting of specified data, \n\
2776 single-stepping, or enabling/disabling other tracepoints, \n\
2777 depending on target's capabilities.");
2778
2779   add_cmd ("tracepoints", class_trace, delete_trace_command, 
2780            "Delete specified tracepoints.\n\
2781 Arguments are tracepoint numbers, separated by spaces.\n\
2782 No argument means delete all tracepoints.",
2783            &deletelist);
2784
2785   add_cmd ("tracepoints", class_trace, disable_trace_command, 
2786            "Disable specified tracepoints.\n\
2787 Arguments are tracepoint numbers, separated by spaces.\n\
2788 No argument means disable all tracepoints.",
2789            &disablelist);
2790
2791   add_cmd ("tracepoints", class_trace, enable_trace_command, 
2792            "Enable specified tracepoints.\n\
2793 Arguments are tracepoint numbers, separated by spaces.\n\
2794 No argument means enable all tracepoints.",
2795            &enablelist);
2796
2797   add_com ("trace", class_trace, trace_command,
2798            "Set a tracepoint at a specified line or function or address.\n\
2799 Argument may be a line number, function name, or '*' plus an address.\n\
2800 For a line number or function, trace at the start of its code.\n\
2801 If an address is specified, trace at that exact address.\n\n\
2802 Do \"help tracepoints\" for info on other tracepoint commands.");
2803
2804   add_com_alias ("tp",   "trace", class_alias, 0);
2805   add_com_alias ("tr",   "trace", class_alias, 1);
2806   add_com_alias ("tra",  "trace", class_alias, 1);
2807   add_com_alias ("trac", "trace", class_alias, 1);
2808 }
2809