import gdb-1999-05-25 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     signal (STOP_SIGNAL, stop_sig);
839 #endif
840   old_chain = make_cleanup ((make_cleanup_func) free_actions, (void *) t);
841   while (1)
842     {
843       /* Make sure that all output has been output.  Some machines may let
844          you get away with leaving out some of the gdb_flush, but not all.  */
845       wrap_here ("");
846       gdb_flush (gdb_stdout);
847       gdb_flush (gdb_stderr);
848
849       if (readline_hook && instream == NULL)
850         line = (*readline_hook) (prompt);
851       else if (instream == stdin && ISATTY (instream))
852         {
853           line = readline (prompt);
854           if (line && *line)            /* add it to command history */
855             add_history (line);
856         }
857       else
858         line = gdb_readline (0);
859
860       linetype = validate_actionline (&line, t);
861       if (linetype == BADLINE)
862         continue;       /* already warned -- collect another line */
863
864       temp = xmalloc (sizeof (struct action_line));
865       temp->next = NULL;
866       temp->action = line;
867
868       if (next == NULL)         /* first action for this tracepoint? */
869         t->actions = next = temp;
870       else
871         {
872           next->next = temp;
873           next = temp;
874         }
875
876       if (linetype == STEPPING) /* begin "while-stepping" */
877         {
878           if (prompt == prompt2)
879             {
880               warning ("Already processing 'while-stepping'");
881               continue;
882             }
883           else
884             prompt = prompt2;   /* change prompt for stepping actions */
885         }
886       else if (linetype == END)
887         {
888           if (prompt == prompt2)
889             {
890               prompt = prompt1; /* end of single-stepping actions */
891             }
892           else
893             { /* end of actions */
894               if (t->actions->next == NULL)
895                 {
896                   /* an "end" all by itself with no other actions means
897                      this tracepoint has no actions.  Discard empty list. */
898                   free_actions (t);
899                 }
900               break;
901             }
902         }
903     }
904 #ifdef STOP_SIGNAL
905   if (job_control)
906     signal (STOP_SIGNAL, SIG_DFL);
907 #endif
908   immediate_quit = 0;
909   discard_cleanups (old_chain);
910 }
911
912 /* worker function */
913 enum actionline_type
914 validate_actionline (line, t)
915      char **line;
916      struct tracepoint *t;
917 {
918   struct cmd_list_element *c;
919   struct expression *exp = NULL;
920   value_ptr temp, temp2;
921   struct cleanup *old_chain = NULL;
922   char *p;
923
924   for (p = *line; isspace (*p); )
925     p++;
926
927   /* symbol lookup etc. */
928   if (*p == '\0')       /* empty line: just prompt for another line. */
929     return BADLINE;
930
931   if (*p == '#')        /* comment line */
932     return GENERIC;
933
934   c = lookup_cmd (&p, cmdlist, "", -1, 1);
935   if (c == 0)
936     {
937       warning ("'%s' is not an action that I know, or is ambiguous.", p);
938       return BADLINE;
939     }
940     
941   if (c->function.cfunc == collect_pseudocommand)
942     {
943       struct agent_expr *aexpr;
944       struct agent_reqs areqs;
945
946       do {                      /* repeat over a comma-separated list */
947         QUIT;                   /* allow user to bail out with ^C */
948         while (isspace (*p))
949           p++;
950
951         if (*p == '$')                  /* look for special pseudo-symbols */
952           {
953             long typecode, size;
954             bfd_signed_vma offset;
955
956             if ((0 == strncasecmp ("reg", p + 1, 3)) ||
957                 (0 == strncasecmp ("arg", p + 1, 3)) ||
958                 (0 == strncasecmp ("loc", p + 1, 3)))
959               {
960                 p = strchr (p, ',');
961                 continue;
962               }
963             /* else fall thru, treat p as an expression and parse it! */
964           }
965         exp   = parse_exp_1 (&p, block_for_pc (t->address), 1);
966         old_chain = make_cleanup ((make_cleanup_func) free_current_contents, 
967                                   &exp);
968
969         if (exp->elts[0].opcode == OP_VAR_VALUE)
970           {
971             if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_CONST)
972               {
973                 warning ("%s is constant (value %d): will not be collected.",
974                          SYMBOL_NAME (exp->elts[2].symbol),
975                          SYMBOL_VALUE (exp->elts[2].symbol));
976                 return BADLINE;
977               }
978             else if (SYMBOL_CLASS (exp->elts[2].symbol) == LOC_OPTIMIZED_OUT)
979               {
980                 warning ("%s is optimized away and cannot be collected.",
981                          SYMBOL_NAME (exp->elts[2].symbol));
982                 return BADLINE;
983               }
984           }
985
986         /* we have something to collect, make sure that the expr to
987            bytecode translator can handle it and that it's not too long */
988         aexpr = gen_trace_for_expr (t->address, exp);
989         (void) make_cleanup ((make_cleanup_func) free_agent_expr, aexpr);
990
991         if (aexpr->len > MAX_AGENT_EXPR_LEN)
992           error ("expression too complicated, try simplifying");
993
994         ax_reqs(aexpr, &areqs);
995         (void) make_cleanup (free, areqs.reg_mask);
996
997         if (areqs.flaw != agent_flaw_none)
998           error ("malformed expression");
999
1000         if (areqs.min_height < 0)
1001           error ("gdb: Internal error: expression has min height < 0");
1002
1003         if (areqs.max_height > 20)
1004           error ("expression too complicated, try simplifying");
1005
1006         do_cleanups (old_chain);
1007       } while (p && *p++ == ',');
1008       return GENERIC;
1009     }
1010   else if (c->function.cfunc == while_stepping_pseudocommand)
1011     {
1012       char *steparg;    /* in case warning is necessary */
1013
1014       while (isspace (*p))
1015         p++;
1016       steparg = p;
1017
1018       if (*p == '\0' ||
1019           (t->step_count = strtol (p, &p, 0)) == 0)
1020         {
1021           warning ("bad step-count: command ignored.", *line);
1022           return BADLINE;
1023         }
1024       return STEPPING;
1025     }
1026   else if (c->function.cfunc == end_actions_pseudocommand)
1027     return END;
1028   else
1029     {
1030       warning ("'%s' is not a supported tracepoint action.", *line);
1031       return BADLINE;
1032     }
1033 }
1034
1035 /* worker function */
1036 void 
1037 free_actions (t)
1038      struct tracepoint *t;
1039 {
1040   struct action_line *line, *next;
1041
1042   for (line = t->actions; line; line = next)
1043     {
1044       next = line->next;
1045       if (line->action) 
1046         free (line->action);
1047       free (line);
1048     }
1049   t->actions = NULL;
1050 }
1051
1052 struct memrange {
1053   int type;             /* 0 for absolute memory range, else basereg number */
1054   bfd_signed_vma start;
1055   bfd_signed_vma end;
1056 };
1057
1058 struct collection_list {
1059   unsigned char regs_mask[8];   /* room for up to 256 regs */
1060   long listsize;
1061   long next_memrange;
1062   struct memrange *list;
1063   long aexpr_listsize;          /* size of array pointed to by expr_list elt */
1064   long next_aexpr_elt;
1065   struct agent_expr **aexpr_list;
1066   
1067 } tracepoint_list, stepping_list;
1068
1069 /* MEMRANGE functions: */
1070
1071 static int memrange_cmp PARAMS ((const void *, const void *));
1072
1073 /* compare memranges for qsort */
1074 static int
1075 memrange_cmp (va, vb)
1076      const void *va;
1077      const void *vb;
1078 {
1079   const struct memrange *a = va, *b = vb;
1080
1081   if (a->type < b->type)
1082     return -1;
1083   if (a->type > b->type)
1084     return  1;
1085   if (a->type == 0)
1086     {
1087       if ((bfd_vma) a->start  < (bfd_vma) b->start)  return -1;
1088       if ((bfd_vma) a->start  > (bfd_vma) b->start)  return  1;
1089     }
1090   else
1091     {
1092       if (a->start  < b->start)
1093         return -1;
1094       if (a->start  > b->start)
1095         return  1;
1096     }
1097   return 0;
1098 }
1099
1100 /* Sort the memrange list using qsort, and merge adjacent memranges */
1101 static void
1102 memrange_sortmerge (memranges)
1103      struct collection_list *memranges;
1104 {
1105   int a, b;
1106
1107   qsort (memranges->list, memranges->next_memrange, 
1108          sizeof (struct memrange), memrange_cmp);
1109   if (memranges->next_memrange > 0)
1110     {
1111       for (a = 0, b = 1; b < memranges->next_memrange; b++)
1112         {
1113           if (memranges->list[a].type == memranges->list[b].type &&
1114               memranges->list[b].start - memranges->list[a].end <= 
1115               MAX_REGISTER_VIRTUAL_SIZE)
1116             {
1117               /* memrange b starts before memrange a ends; merge them.  */
1118               if (memranges->list[b].end > memranges->list[a].end)
1119                 memranges->list[a].end = memranges->list[b].end;
1120               continue;         /* next b, same a */
1121             }
1122           a++;                  /* next a */
1123           if (a != b)
1124             memcpy (&memranges->list[a], &memranges->list[b], 
1125                     sizeof (struct memrange));
1126         }
1127       memranges->next_memrange = a + 1;
1128     }
1129 }
1130
1131 /* Add a register to a collection list */
1132 static void
1133 add_register (collection, regno)
1134      struct collection_list *collection;
1135      unsigned long regno;
1136 {
1137   if (info_verbose)
1138     printf_filtered ("collect register %d\n", regno);
1139   if (regno > (8 * sizeof (collection->regs_mask)))
1140     error ("Internal: register number %d too large for tracepoint",
1141            regno);
1142   collection->regs_mask [regno / 8] |= 1 << (regno  % 8);
1143 }
1144
1145 /* Add a memrange to a collection list */
1146 static void
1147 add_memrange (memranges, type, base, len)
1148      struct collection_list *memranges;
1149      int type;
1150      bfd_signed_vma base;
1151      unsigned long len;
1152 {
1153   if (info_verbose)
1154     printf_filtered ("(%d,0x%x,%d)\n", type, base, len);
1155   /* type: 0 == memory, n == basereg */
1156   memranges->list[memranges->next_memrange].type  = type;
1157   /* base: addr if memory, offset if reg relative. */
1158   memranges->list[memranges->next_memrange].start = base;
1159   /* len: we actually save end (base + len) for convenience */
1160   memranges->list[memranges->next_memrange].end   = base + len;
1161   memranges->next_memrange++;
1162   if (memranges->next_memrange >= memranges->listsize)
1163     {
1164       memranges->listsize *= 2;
1165       memranges->list = xrealloc (memranges->list, 
1166                                   memranges->listsize);
1167     }
1168
1169   if (type != -1)       /* better collect the base register! */
1170     add_register (memranges, type);
1171 }
1172
1173 /* Add a symbol to a collection list */
1174 static void
1175 collect_symbol (collect, sym, frame_regno, frame_offset)
1176      struct collection_list *collect;
1177      struct symbol *sym;
1178      long frame_regno;
1179      long frame_offset;
1180 {
1181   unsigned long  len;
1182   unsigned long  reg;
1183   bfd_signed_vma offset;
1184
1185   len  = TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym)));
1186   switch (SYMBOL_CLASS (sym)) {
1187   default:
1188     printf_filtered ("%s: don't know symbol class %d\n",
1189                      SYMBOL_NAME (sym), SYMBOL_CLASS (sym));
1190     break;
1191   case LOC_CONST:
1192     printf_filtered ("%s is constant, value is %d: will not be collected.\n",
1193                      SYMBOL_NAME (sym), SYMBOL_VALUE (sym));
1194     break;
1195   case LOC_STATIC:
1196     offset = SYMBOL_VALUE_ADDRESS (sym); 
1197     if (info_verbose)
1198       printf_filtered ("LOC_STATIC %s: collect %d bytes at 0x%08x\n",
1199                        SYMBOL_NAME (sym), len, offset);
1200     add_memrange (collect, -1, offset, len);    /* 0 == memory */
1201     break;
1202   case LOC_REGISTER:
1203   case LOC_REGPARM:
1204     reg = SYMBOL_VALUE (sym); 
1205     if (info_verbose)
1206       printf_filtered ("LOC_REG[parm] %s: ", SYMBOL_NAME (sym));
1207     add_register (collect, reg);
1208     /* check for doubles stored in two registers */
1209     /* FIXME: how about larger types stored in 3 or more regs? */
1210     if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
1211         len > REGISTER_RAW_SIZE (reg))
1212       add_register (collect, reg + 1);
1213     break;
1214   case LOC_REF_ARG:
1215     printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
1216     printf_filtered ("       (will not collect %s)\n", 
1217                      SYMBOL_NAME (sym));
1218     break;
1219   case LOC_ARG:
1220     reg    = frame_regno;
1221     offset = frame_offset + SYMBOL_VALUE (sym);
1222     if (info_verbose)
1223       {
1224         printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1225                          SYMBOL_NAME (sym), len);
1226         printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
1227       }
1228     add_memrange (collect, reg, offset, len);
1229     break;
1230   case LOC_REGPARM_ADDR:
1231     reg = SYMBOL_VALUE (sym);
1232     offset = 0;
1233     if (info_verbose)
1234       {
1235         printf_filtered ("LOC_REGPARM_ADDR %s: Collect %d bytes at offset",
1236                          SYMBOL_NAME (sym), len);
1237         printf_filtered (" %d from reg %d\n", offset, reg);
1238       }
1239     add_memrange (collect, reg, offset, len);
1240     break;
1241   case LOC_LOCAL:
1242   case LOC_LOCAL_ARG:
1243     reg    = frame_regno;
1244     offset = frame_offset + SYMBOL_VALUE (sym);
1245     if (info_verbose)
1246       {
1247         printf_filtered ("LOC_LOCAL %s: Collect %d bytes at offset",
1248                          SYMBOL_NAME (sym), len);
1249         printf_filtered (" %d from frame ptr reg %d\n", offset, reg);
1250       }
1251     add_memrange (collect, reg, offset, len);
1252     break;
1253   case LOC_BASEREG:
1254   case LOC_BASEREG_ARG:
1255     reg = SYMBOL_BASEREG (sym);
1256     offset  = SYMBOL_VALUE (sym);
1257     if (info_verbose)
1258       {
1259         printf_filtered ("LOC_BASEREG %s: collect %d bytes at offset %d from basereg %d\n", 
1260                          SYMBOL_NAME (sym), len, offset, reg);
1261       }
1262     add_memrange (collect, reg, offset, len);
1263     break;
1264   case LOC_UNRESOLVED:
1265     printf_filtered ("Don't know LOC_UNRESOLVED %s\n", SYMBOL_NAME (sym));
1266     break;
1267   case LOC_OPTIMIZED_OUT:
1268     printf_filtered ("%s has been optimized out of existance.\n",
1269                      SYMBOL_NAME (sym));
1270     break;
1271   }
1272 }
1273
1274 /* Add all locals (or args) symbols to collection list */
1275 static void
1276 add_local_symbols (collect, pc, frame_regno, frame_offset, type)
1277      struct collection_list *collect;
1278      CORE_ADDR pc;
1279      long frame_regno;
1280      long frame_offset;
1281      int type;
1282 {
1283   struct symbol *sym;
1284   struct block  *block;
1285   int i, nsyms, count = 0;
1286
1287   block = block_for_pc (pc);
1288   while (block != 0)
1289     {
1290       QUIT;                             /* allow user to bail out with ^C */
1291       nsyms = BLOCK_NSYMS (block);
1292       for (i = 0; i < nsyms; i++)
1293         {
1294           sym = BLOCK_SYM (block, i);
1295           switch (SYMBOL_CLASS (sym)) {
1296           case LOC_LOCAL:
1297           case LOC_STATIC:
1298           case LOC_REGISTER:
1299           case LOC_BASEREG:
1300             if (type == 'L')    /* collecting Locals */
1301               {
1302                 count++;
1303                 collect_symbol (collect, sym, frame_regno, frame_offset);
1304               }
1305             break;
1306           case LOC_ARG:
1307           case LOC_LOCAL_ARG:
1308           case LOC_REF_ARG:
1309           case LOC_REGPARM:
1310           case LOC_REGPARM_ADDR:
1311           case LOC_BASEREG_ARG:
1312             if (type == 'A')    /* collecting Arguments */
1313               {
1314                 count++;
1315                 collect_symbol (collect, sym, frame_regno, frame_offset);
1316               }
1317           }
1318         }
1319       if (BLOCK_FUNCTION (block))
1320         break;
1321       else
1322         block = BLOCK_SUPERBLOCK (block);
1323     }
1324   if (count == 0)
1325     warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
1326 }
1327
1328 /* worker function */
1329 static void
1330 clear_collection_list (list)
1331      struct collection_list *list;
1332 {
1333   int ndx;
1334
1335   list->next_memrange = 0;
1336   for (ndx = 0; ndx < list->next_aexpr_elt; ndx++)
1337     {
1338       free_agent_expr(list->aexpr_list[ndx]);
1339       list->aexpr_list[ndx] = NULL;
1340     }
1341   list->next_aexpr_elt = 0;
1342   memset (list->regs_mask, 0, sizeof (list->regs_mask));
1343 }
1344
1345 /* reduce a collection list to string form (for gdb protocol) */
1346 static char **
1347 stringify_collection_list (list, string)
1348      struct collection_list *list;
1349      char *string;
1350 {
1351   char temp_buf[2048];
1352   int count;
1353   int ndx = 0;
1354   char *(*str_list)[];
1355   char *end;
1356   long  i;
1357
1358   count = 1 + list->next_memrange + list->next_aexpr_elt + 1;
1359   str_list = (char *(*)[])xmalloc(count * sizeof (char *));
1360
1361   for (i = sizeof (list->regs_mask) - 1; i > 0; i--)
1362     if (list->regs_mask[i] != 0)        /* skip leading zeroes in regs_mask */
1363       break;
1364   if (list->regs_mask[i] != 0)  /* prepare to send regs_mask to the stub */
1365     {
1366       if (info_verbose)
1367         printf_filtered ("\nCollecting registers (mask): 0x");
1368       end = temp_buf;
1369       *end++='R';
1370       for (; i >= 0; i--)
1371         {
1372           QUIT;                         /* allow user to bail out with ^C */
1373           if (info_verbose)
1374             printf_filtered ("%02X", list->regs_mask[i]);
1375           sprintf (end,  "%02X", list->regs_mask[i]);
1376           end += 2;
1377         }
1378       (*str_list)[ndx] = savestring(temp_buf, end - temp_buf);
1379       ndx++;
1380     }
1381   if (info_verbose)
1382     printf_filtered ("\n");
1383   if (list->next_memrange > 0 && info_verbose)
1384     printf_filtered ("Collecting memranges: \n");
1385   for (i = 0, count = 0, end = temp_buf; i < list->next_memrange; i++)
1386     {
1387       QUIT;                     /* allow user to bail out with ^C */
1388       if (info_verbose)
1389         printf_filtered ("(%d, 0x%x, %d)\n", 
1390                          list->list[i].type, 
1391                          list->list[i].start, 
1392                          list->list[i].end - list->list[i].start);
1393       if (count + 27 > MAX_AGENT_EXPR_LEN)
1394         {
1395           (*str_list)[ndx] = savestring(temp_buf, count);
1396           ndx++;
1397           count = 0;
1398           end = temp_buf;
1399         }
1400       sprintf (end, "M%X,%X,%X", 
1401                list->list[i].type, 
1402                list->list[i].start, 
1403                list->list[i].end - list->list[i].start);
1404       count += strlen (end);
1405       end += strlen (end);
1406     }
1407
1408   for (i = 0; i < list->next_aexpr_elt; i++)
1409     {
1410       QUIT;                     /* allow user to bail out with ^C */
1411       if ((count + 10 + 2 * list->aexpr_list[i]->len) > MAX_AGENT_EXPR_LEN)
1412         {
1413           (*str_list)[ndx] = savestring(temp_buf, count);
1414           ndx++;
1415           count = 0;
1416           end = temp_buf;
1417         }
1418       sprintf (end, "X%08X,", list->aexpr_list[i]->len);
1419       end += 10;                /* 'X' + 8 hex digits + ',' */
1420       count += 10;
1421
1422       end = mem2hex(list->aexpr_list[i]->buf, end, list->aexpr_list[i]->len);
1423       count += 2 * list->aexpr_list[i]->len;
1424     }
1425
1426   if (count != 0)
1427     {
1428       (*str_list)[ndx] = savestring(temp_buf, count);
1429       ndx++;
1430       count = 0;
1431       end = temp_buf;
1432     }
1433   (*str_list)[ndx] = NULL;
1434
1435   if (ndx == 0)
1436     return NULL;
1437   else
1438     return *str_list;
1439 }
1440
1441 static void
1442 free_actions_list_cleanup_wrapper (al)
1443      void *al;
1444 {
1445   free_actions_list (al);
1446 }
1447
1448 static void
1449 free_actions_list(actions_list)
1450      char **actions_list;
1451 {
1452   int ndx;
1453
1454   if (actions_list == 0)
1455     return;
1456
1457   for (ndx = 0; actions_list[ndx]; ndx++)
1458     free(actions_list[ndx]);
1459
1460   free(actions_list);
1461 }
1462
1463 /* render all actions into gdb protocol */
1464 static void
1465 encode_actions (t, tdp_actions, stepping_actions)
1466      struct tracepoint  *t;
1467      char              ***tdp_actions;
1468      char              ***stepping_actions;
1469 {
1470   static char        tdp_buff[2048], step_buff[2048];
1471   char               *action_exp;
1472   struct expression  *exp = NULL;
1473   struct action_line *action;
1474   bfd_signed_vma      offset;
1475   long                i;
1476   value_ptr           tempval;
1477   struct collection_list  *collect;
1478   struct cmd_list_element *cmd;
1479   struct agent_expr *aexpr;
1480   long                frame_reg, frame_offset;
1481
1482
1483   clear_collection_list (&tracepoint_list);
1484   clear_collection_list (&stepping_list);
1485   collect = &tracepoint_list;
1486
1487   *tdp_actions = NULL;
1488   *stepping_actions = NULL;
1489
1490   TARGET_VIRTUAL_FRAME_POINTER (t->address, &frame_reg, &frame_offset);
1491
1492   for (action = t->actions; action; action = action->next)
1493     {
1494       QUIT;                     /* allow user to bail out with ^C */
1495       action_exp = action->action;
1496       while (isspace (*action_exp))
1497         action_exp++;
1498
1499       if (*action_exp == '#')   /* comment line */
1500         return;
1501
1502       cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
1503       if (cmd == 0)
1504         error ("Bad action list item: %s", action_exp);
1505
1506       if (cmd->function.cfunc == collect_pseudocommand)
1507         {
1508           do {  /* repeat over a comma-separated list */
1509             QUIT;               /* allow user to bail out with ^C */
1510             while (isspace (*action_exp))
1511               action_exp++;
1512
1513             if (0 == strncasecmp ("$reg", action_exp, 4))
1514               {
1515                 for (i = 0; i < NUM_REGS; i++)
1516                   add_register (collect, i);
1517                 action_exp = strchr (action_exp, ','); /* more? */
1518               }
1519             else if (0 == strncasecmp ("$arg", action_exp, 4))
1520               {
1521                 add_local_symbols (collect, 
1522                                    t->address, 
1523                                    frame_reg,
1524                                    frame_offset,
1525                                    'A');
1526                 action_exp = strchr (action_exp, ','); /* more? */
1527               }
1528             else if (0 == strncasecmp ("$loc", action_exp, 4))
1529               {
1530                 add_local_symbols (collect, 
1531                                    t->address, 
1532                                    frame_reg,
1533                                    frame_offset,
1534                                    'L');
1535                 action_exp = strchr (action_exp, ','); /* more? */
1536               }
1537             else
1538               {
1539                 unsigned long addr, len;
1540                 struct cleanup *old_chain = NULL;
1541                 struct cleanup *old_chain1 = NULL;
1542                 struct agent_reqs areqs;
1543
1544                 exp = parse_exp_1 (&action_exp, block_for_pc (t->address), 1);
1545                 old_chain = make_cleanup ((make_cleanup_func) 
1546                                           free_current_contents, &exp);
1547
1548                 switch (exp->elts[0].opcode) {
1549                 case OP_REGISTER:
1550                   i = exp->elts[1].longconst;
1551                   if (info_verbose)
1552                     printf_filtered ("OP_REGISTER: ");
1553                   add_register (collect, i);
1554                   break;
1555
1556                 case UNOP_MEMVAL:
1557                   /* safe because we know it's a simple expression */
1558                   tempval = evaluate_expression (exp);
1559                   addr = VALUE_ADDRESS (tempval) + VALUE_OFFSET (tempval);
1560                   len = TYPE_LENGTH (check_typedef (exp->elts[1].type));
1561                   add_memrange (collect, -1, addr, len);
1562                   break;
1563
1564                 case OP_VAR_VALUE:
1565                   collect_symbol (collect, 
1566                                   exp->elts[2].symbol,
1567                                   frame_reg,
1568                                   frame_offset);
1569                   break;
1570
1571                 default:        /* full-fledged expression */
1572                   aexpr = gen_trace_for_expr (t->address, exp);
1573
1574                   old_chain1 = make_cleanup ((make_cleanup_func) 
1575                                              free_agent_expr, aexpr);
1576
1577                   ax_reqs (aexpr, &areqs);
1578                   if (areqs.flaw != agent_flaw_none)
1579                     error ("malformed expression");
1580
1581                   if (areqs.min_height < 0)
1582                     error ("gdb: Internal error: expression has min height < 0");
1583                   if (areqs.max_height > 20)
1584                     error ("expression too complicated, try simplifying");
1585
1586                   discard_cleanups (old_chain1);
1587                   add_aexpr (collect, aexpr);
1588
1589                   /* take care of the registers */
1590                   if (areqs.reg_mask_len > 0)
1591                     {
1592                       int ndx1;
1593                       int ndx2;
1594
1595                       for (ndx1 = 0; ndx1 < areqs.reg_mask_len; ndx1++)
1596                         {
1597                           QUIT;         /* allow user to bail out with ^C */
1598                           if (areqs.reg_mask[ndx1] != 0)
1599                             {
1600                               /* assume chars have 8 bits */
1601                               for (ndx2 = 0; ndx2 < 8; ndx2++)
1602                                 if (areqs.reg_mask[ndx1] & (1 << ndx2))
1603                                   /* it's used -- record it */
1604                                   add_register (collect, ndx1 * 8 + ndx2);
1605                             }
1606                         }
1607                     }
1608                   break;
1609                 }       /* switch */
1610                 do_cleanups (old_chain);
1611               }         /* do */
1612           } while (action_exp && *action_exp++ == ',');
1613         }               /* if */
1614       else if (cmd->function.cfunc == while_stepping_pseudocommand)
1615         {
1616           collect = &stepping_list;
1617         }
1618       else if (cmd->function.cfunc == end_actions_pseudocommand)
1619         {
1620           if (collect == &stepping_list)        /* end stepping actions */
1621             collect = &tracepoint_list;
1622           else
1623             break;                      /* end tracepoint actions */
1624         }
1625     }                   /* for */
1626   memrange_sortmerge (&tracepoint_list); 
1627   memrange_sortmerge (&stepping_list); 
1628
1629   *tdp_actions      = stringify_collection_list (&tracepoint_list, &tdp_buff);
1630   *stepping_actions = stringify_collection_list (&stepping_list,   &step_buff);
1631 }
1632
1633 static void
1634 add_aexpr(collect, aexpr)
1635      struct collection_list *collect;
1636      struct agent_expr *aexpr;
1637 {
1638   if (collect->next_aexpr_elt >= collect->aexpr_listsize)
1639     {
1640       collect->aexpr_list =
1641         xrealloc (collect->aexpr_list,
1642                   2 * collect->aexpr_listsize * sizeof (struct agent_expr *));
1643       collect->aexpr_listsize *= 2;
1644     }
1645   collect->aexpr_list[collect->next_aexpr_elt] = aexpr;
1646   collect->next_aexpr_elt++;
1647 }
1648
1649 static char target_buf[2048];
1650
1651 /* Set "transparent" memory ranges
1652
1653    Allow trace mechanism to treat text-like sections
1654    (and perhaps all read-only sections) transparently, 
1655    i.e. don't reject memory requests from these address ranges
1656    just because they haven't been collected.  */
1657
1658 static void
1659 remote_set_transparent_ranges (void)
1660 {
1661   extern bfd *exec_bfd;
1662   asection *s;
1663   bfd_size_type size;
1664   bfd_vma lma;
1665   int anysecs = 0;
1666
1667   if (!exec_bfd)
1668     return;             /* no information to give. */
1669
1670   strcpy (target_buf, "QTro");
1671   for (s = exec_bfd->sections; s; s = s->next)
1672     {
1673       char tmp[40];
1674
1675       if ((s->flags & SEC_LOAD)     == 0 ||
1676        /* (s->flags & SEC_CODE)     == 0 || */
1677           (s->flags & SEC_READONLY) == 0)
1678         continue;
1679
1680       anysecs = 1;
1681       lma  = s->lma;
1682       size = bfd_get_section_size_before_reloc (s);
1683       sprintf (tmp, ":%x,%x", lma, lma + size);
1684       strcat (target_buf, tmp);
1685     }
1686   if (anysecs)
1687     {
1688       putpkt (target_buf);
1689       getpkt (target_buf, 0);
1690     }
1691 }
1692
1693 /* tstart command:
1694  
1695    Tell target to clear any previous trace experiment.
1696    Walk the list of tracepoints, and send them (and their actions)
1697    to the target.  If no errors, 
1698    Tell target to start a new trace experiment.  */
1699
1700 static void
1701 trace_start_command (args, from_tty)
1702      char *args;
1703      int from_tty;
1704 { /* STUB_COMM MOSTLY_IMPLEMENTED */
1705   struct tracepoint *t;
1706   char buf[2048];
1707   char **tdp_actions;
1708   char **stepping_actions;
1709   int ndx;
1710   struct cleanup *old_chain = NULL;
1711
1712   dont_repeat ();       /* like "run", dangerous to repeat accidentally */
1713   
1714   if (target_is_remote ())
1715     {
1716       putpkt ("QTinit");
1717       remote_get_noisy_reply (target_buf);
1718       if (strcmp (target_buf, "OK"))
1719         error ("Target does not support this command.");
1720
1721       ALL_TRACEPOINTS (t)
1722         {
1723           int ss_count;         /* if actions include singlestepping */
1724           int disable_mask;     /* ??? */
1725           int enable_mask;      /* ??? */
1726
1727           sprintf (buf, "QTDP:%x:%x:%c:%x:%x", t->number, t->address, 
1728                    t->enabled == enabled ? 'E' : 'D', 
1729                    t->step_count, t->pass_count);
1730
1731           if (t->actions)
1732             strcat (buf, "-");
1733           putpkt (buf);
1734           remote_get_noisy_reply (target_buf);
1735           if (strcmp (target_buf, "OK"))
1736             error ("Target does not support tracepoints.");
1737
1738           if (t->actions)
1739             {
1740               encode_actions (t, &tdp_actions, &stepping_actions);
1741               old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
1742                                         tdp_actions);
1743               (void) make_cleanup (free_actions_list_cleanup_wrapper,
1744                                    stepping_actions);
1745
1746               /* do_single_steps (t); */
1747               if (tdp_actions)
1748                 {
1749                   for (ndx = 0; tdp_actions[ndx]; ndx++)
1750                     {
1751                       QUIT;             /* allow user to bail out with ^C */
1752                       sprintf (buf, "QTDP:-%x:%x:%s%c",
1753                                t->number, t->address,
1754                                tdp_actions[ndx],
1755                                ((tdp_actions[ndx+1] || stepping_actions)
1756                                 ? '-' : 0));
1757                       putpkt (buf);
1758                       remote_get_noisy_reply (target_buf);
1759                       if (strcmp (target_buf, "OK"))
1760                         error ("Error on target while setting tracepoints.");
1761                     }
1762                 }
1763               if (stepping_actions)
1764                 {
1765                   for (ndx = 0; stepping_actions[ndx]; ndx++)
1766                     {
1767                       QUIT;             /* allow user to bail out with ^C */
1768                       sprintf (buf, "QTDP:-%x:%x:%s%s%s",
1769                                t->number, t->address,
1770                                ((ndx == 0) ? "S" : ""),
1771                                stepping_actions[ndx],
1772                                (stepping_actions[ndx+1] ? "-" : ""));
1773                       putpkt (buf);
1774                       remote_get_noisy_reply (target_buf);
1775                       if (strcmp (target_buf, "OK"))
1776                         error ("Error on target while setting tracepoints.");
1777                     }
1778                 }
1779
1780               do_cleanups (old_chain);
1781             }
1782         }
1783       /* Tell target to treat text-like sections as transparent */
1784       remote_set_transparent_ranges ();
1785       /* Now insert traps and begin collecting data */
1786       putpkt ("QTStart");
1787       remote_get_noisy_reply (target_buf);
1788       if (strcmp (target_buf, "OK"))
1789         error ("Bogus reply from target: %s", target_buf);
1790       set_traceframe_num (-1);  /* all old traceframes invalidated */
1791       set_tracepoint_num (-1);
1792       set_traceframe_context(-1);
1793       trace_running_p = 1;
1794       if (trace_start_stop_hook)
1795         trace_start_stop_hook(1, from_tty);
1796       
1797     }
1798   else
1799     error ("Trace can only be run on remote targets.");
1800 }
1801
1802 /* tstop command */
1803 static void
1804 trace_stop_command (args, from_tty)
1805      char *args;
1806      int from_tty;
1807 { /* STUB_COMM IS_IMPLEMENTED */
1808   if (target_is_remote ())
1809     {
1810       putpkt ("QTStop");
1811       remote_get_noisy_reply (target_buf);
1812       if (strcmp (target_buf, "OK"))
1813         error ("Bogus reply from target: %s", target_buf);
1814       trace_running_p = 0;
1815       if (trace_start_stop_hook)
1816         trace_start_stop_hook(0, from_tty);
1817     }
1818   else
1819     error ("Trace can only be run on remote targets.");
1820 }
1821
1822 unsigned long trace_running_p;
1823
1824 /* tstatus command */
1825 static void
1826 trace_status_command (args, from_tty)
1827      char *args;
1828      int from_tty;
1829 { /* STUB_COMM IS_IMPLEMENTED */
1830   if (target_is_remote ())
1831     {
1832       putpkt ("qTStatus");
1833       remote_get_noisy_reply (target_buf);
1834
1835       if (target_buf[0] != 'T' ||
1836           (target_buf[1] != '0' && target_buf[1] != '1'))
1837         error ("Bogus reply from target: %s", target_buf);
1838
1839       /* exported for use by the GUI */
1840       trace_running_p = (target_buf[1] == '1');
1841     }
1842   else
1843     error ("Trace can only be run on remote targets.");
1844 }
1845
1846 /* Worker function for the various flavors of the tfind command */
1847 static void
1848 finish_tfind_command (msg, from_tty)
1849      char *msg;
1850      int from_tty;
1851 {
1852   int target_frameno = -1, target_tracept = -1;
1853   CORE_ADDR old_frame_addr;
1854   struct symbol *old_func;
1855   char *reply;
1856
1857   old_frame_addr = FRAME_FP (get_current_frame ());
1858   old_func       = find_pc_function (read_pc ());
1859
1860   putpkt (msg);
1861   reply = remote_get_noisy_reply (msg);
1862
1863   while (reply && *reply)
1864     switch (*reply) {
1865     case 'F':
1866       if ((target_frameno = (int) strtol (++reply, &reply, 16)) == -1)
1867         { 
1868           /* A request for a non-existant trace frame has failed.
1869              Our response will be different, depending on FROM_TTY:
1870
1871              If FROM_TTY is true, meaning that this command was 
1872              typed interactively by the user, then give an error
1873              and DO NOT change the state of traceframe_number etc.
1874
1875              However if FROM_TTY is false, meaning that we're either
1876              in a script, a loop, or a user-defined command, then 
1877              DON'T give an error, but DO change the state of
1878              traceframe_number etc. to invalid.
1879
1880              The rationalle is that if you typed the command, you
1881              might just have committed a typo or something, and you'd
1882              like to NOT lose your current debugging state.  However
1883              if you're in a user-defined command or especially in a
1884              loop, then you need a way to detect that the command
1885              failed WITHOUT aborting.  This allows you to write
1886              scripts that search thru the trace buffer until the end,
1887              and then continue on to do something else.  */
1888
1889           if (from_tty)
1890             error ("Target failed to find requested trace frame.");
1891           else
1892             {
1893               if (info_verbose)
1894                 printf_filtered ("End of trace buffer.\n");
1895               /* The following will not recurse, since it's special-cased */
1896               trace_find_command ("-1", from_tty);
1897               reply = NULL;     /* break out of loop, 
1898                                    (avoid recursive nonsense) */
1899             }
1900         }
1901       break;
1902     case 'T':
1903       if ((target_tracept = (int) strtol (++reply, &reply, 16)) == -1)
1904         error ("Target failed to find requested trace frame.");
1905       break;
1906     case 'O':   /* "OK"? */
1907       if (reply[1] == 'K' && reply[2] == '\0')
1908         reply += 2;
1909       else
1910         error ("Bogus reply from target: %s", reply);
1911       break;
1912     default:
1913       error ("Bogus reply from target: %s", reply);
1914     }
1915
1916   flush_cached_frames ();
1917   registers_changed ();
1918   select_frame (get_current_frame (), 0);
1919   set_traceframe_num (target_frameno);
1920   set_tracepoint_num (target_tracept);
1921   if (target_frameno == -1)
1922     set_traceframe_context (-1);
1923   else
1924     set_traceframe_context (read_pc ());
1925
1926   if (from_tty)
1927     {
1928       int source_only;
1929
1930       /* NOTE: in immitation of the step command, try to determine
1931          whether we have made a transition from one function to another.
1932          If so, we'll print the "stack frame" (ie. the new function and
1933          it's arguments) -- otherwise we'll just show the new source line.
1934
1935          This determination is made by checking (1) whether the current
1936          function has changed, and (2) whether the current FP has changed.
1937          Hack: if the FP wasn't collected, either at the current or the
1938          previous frame, assume that the FP has NOT changed.  */
1939
1940       if (old_func       == find_pc_function (read_pc ()) &&
1941          (old_frame_addr == 0 ||
1942           FRAME_FP (get_current_frame ()) == 0 ||
1943           old_frame_addr == FRAME_FP (get_current_frame ())))
1944         source_only = -1;
1945       else
1946         source_only =  1;
1947
1948       print_stack_frame (selected_frame, selected_frame_level, source_only);
1949       do_displays ();
1950     }
1951 }
1952
1953 /* trace_find_command takes a trace frame number n, 
1954    sends "QTFrame:<n>" to the target, 
1955    and accepts a reply that may contain several optional pieces
1956    of information: a frame number, a tracepoint number, and an
1957    indication of whether this is a trap frame or a stepping frame.
1958
1959    The minimal response is just "OK" (which indicates that the 
1960    target does not give us a frame number or a tracepoint number).
1961    Instead of that, the target may send us a string containing
1962    any combination of:
1963         F<hexnum>       (gives the selected frame number)
1964         T<hexnum>       (gives the selected tracepoint number)
1965    */
1966
1967 /* tfind command */
1968 static void
1969 trace_find_command (args, from_tty)
1970      char *args;
1971      int from_tty;
1972 { /* STUB_COMM PART_IMPLEMENTED */
1973   /* this should only be called with a numeric argument */
1974   int frameno = -1;
1975   char *tmp;
1976
1977   if (target_is_remote ())
1978     {
1979       if (trace_find_hook)
1980         trace_find_hook (args, from_tty);  
1981       
1982       if (args == 0 || *args == 0)
1983         { /* TFIND with no args means find NEXT trace frame. */
1984           if (traceframe_number == -1)
1985             frameno = 0;        /* "next" is first one */
1986           else
1987             frameno = traceframe_number + 1;
1988         }
1989       else if (0 == strcmp (args, "-"))
1990         {
1991           if (traceframe_number == -1)
1992             error ("not debugging trace buffer");
1993           else if (from_tty && traceframe_number == 0)
1994             error ("already at start of trace buffer");
1995
1996           frameno = traceframe_number - 1;
1997         }
1998       else
1999         frameno = parse_and_eval_address (args);
2000
2001       if (frameno < -1)
2002         error ("invalid input (%d is less than zero)", frameno);
2003
2004       sprintf (target_buf, "QTFrame:%x", frameno);
2005       finish_tfind_command (target_buf, from_tty);
2006     }
2007   else
2008     error ("Trace can only be run on remote targets.");
2009 }
2010
2011 /* tfind end */
2012 static void
2013 trace_find_end_command (args, from_tty)
2014      char *args;
2015      int from_tty;
2016 {
2017   trace_find_command ("-1", from_tty);
2018 }
2019
2020 /* tfind none */
2021 static void
2022 trace_find_none_command (args, from_tty)
2023      char *args;
2024      int from_tty;
2025 {
2026   trace_find_command ("-1", from_tty);
2027 }
2028
2029 /* tfind start */
2030 static void
2031 trace_find_start_command (args, from_tty)
2032      char *args;
2033      int from_tty;
2034 {
2035   trace_find_command ("0", from_tty);
2036 }
2037
2038 /* tfind pc command */
2039 static void
2040 trace_find_pc_command (args, from_tty)
2041      char *args;
2042      int from_tty;
2043 { /* STUB_COMM PART_IMPLEMENTED */
2044   CORE_ADDR pc;
2045   char *tmp;
2046
2047   if (target_is_remote ())
2048     {
2049       if (args == 0 || *args == 0)
2050         pc = read_pc ();        /* default is current pc */
2051       else
2052         pc = parse_and_eval_address (args);
2053
2054       sprintf (target_buf, "QTFrame:pc:%x", pc);
2055       finish_tfind_command (target_buf, from_tty);
2056     }
2057   else
2058     error ("Trace can only be run on remote targets.");
2059 }
2060
2061 /* tfind tracepoint command */
2062 static void
2063 trace_find_tracepoint_command (args, from_tty)
2064      char *args;
2065      int from_tty;
2066 { /* STUB_COMM PART_IMPLEMENTED */
2067   int tdp;
2068   char buf[40], *tmp;
2069
2070   if (target_is_remote ())
2071     {
2072       if (args == 0 || *args == 0)
2073         if (tracepoint_number == -1)
2074           error ("No current tracepoint -- please supply an argument.");
2075         else
2076           tdp = tracepoint_number;      /* default is current TDP */
2077       else
2078         tdp = parse_and_eval_address (args);
2079
2080       sprintf (target_buf, "QTFrame:tdp:%x", tdp);
2081       finish_tfind_command (target_buf, from_tty);
2082     }
2083   else
2084     error ("Trace can only be run on remote targets.");
2085 }
2086
2087 /* TFIND LINE command:
2088  
2089    This command will take a sourceline for argument, just like BREAK
2090    or TRACE (ie. anything that "decode_line_1" can handle).  
2091    
2092    With no argument, this command will find the next trace frame 
2093    corresponding to a source line OTHER THAN THE CURRENT ONE.  */
2094
2095 static void
2096 trace_find_line_command (args, from_tty)
2097      char *args;
2098      int from_tty;
2099 { /* STUB_COMM PART_IMPLEMENTED */
2100   static CORE_ADDR start_pc, end_pc;
2101   struct symtabs_and_lines sals;
2102   struct symtab_and_line sal;
2103   char *tmp;
2104   struct cleanup *old_chain;
2105
2106   if (target_is_remote ())
2107     {
2108       if (args == 0 || *args == 0)
2109         {
2110           sal = find_pc_line ((get_current_frame ())->pc, 0);
2111           sals.nelts = 1;
2112           sals.sals = (struct symtab_and_line *)
2113             xmalloc (sizeof (struct symtab_and_line));
2114           sals.sals[0] = sal;
2115         }
2116       else
2117         {
2118           sals = decode_line_spec (args, 1);
2119           sal  = sals.sals[0];
2120         }
2121
2122       old_chain = make_cleanup (free, sals.sals);
2123       if (sal.symtab == 0)
2124         {
2125           printf_filtered ("TFIND: No line number information available");
2126           if (sal.pc != 0)
2127             {
2128               /* This is useful for "info line *0x7f34".  If we can't tell the
2129                  user about a source line, at least let them have the symbolic
2130                  address.  */
2131               printf_filtered (" for address ");
2132               wrap_here ("  ");
2133               print_address (sal.pc, gdb_stdout);
2134               printf_filtered (";\n -- will attempt to find by PC. \n");
2135             }
2136           else
2137             {
2138               printf_filtered (".\n");
2139               return;   /* no line, no PC; what can we do? */
2140             }
2141         }
2142       else if (sal.line > 0
2143                && find_line_pc_range (sal, &start_pc, &end_pc))
2144         {
2145           if (start_pc == end_pc)
2146             {
2147               printf_filtered ("Line %d of \"%s\"",
2148                                sal.line, sal.symtab->filename);
2149               wrap_here ("  ");
2150               printf_filtered (" is at address ");
2151               print_address (start_pc, gdb_stdout);
2152               wrap_here ("  ");
2153               printf_filtered (" but contains no code.\n");
2154               sal = find_pc_line (start_pc, 0);
2155               if (sal.line > 0 &&
2156                   find_line_pc_range (sal, &start_pc, &end_pc) &&
2157                   start_pc != end_pc)
2158                 printf_filtered ("Attempting to find line %d instead.\n",
2159                                  sal.line);
2160               else
2161                 error ("Cannot find a good line.");
2162             }
2163         }
2164       else
2165         /* Is there any case in which we get here, and have an address
2166            which the user would want to see?  If we have debugging symbols
2167            and no line numbers?  */
2168         error ("Line number %d is out of range for \"%s\".\n",
2169                sal.line, sal.symtab->filename);
2170
2171       if (args && *args)        /* find within range of stated line */
2172         sprintf (target_buf, "QTFrame:range:%x:%x", start_pc, end_pc - 1);
2173       else                      /* find OUTSIDE OF range of CURRENT line */
2174         sprintf (target_buf, "QTFrame:outside:%x:%x", start_pc, end_pc - 1);
2175       finish_tfind_command (target_buf, from_tty);
2176       do_cleanups (old_chain);
2177     }
2178   else
2179       error ("Trace can only be run on remote targets.");
2180 }
2181
2182 /* tfind range command */
2183 static void
2184 trace_find_range_command (args, from_tty)
2185      char *args;
2186      int from_tty;
2187 { /* STUB_COMM PART_IMPLEMENTED */
2188   static CORE_ADDR start, stop;
2189   char *tmp;
2190
2191   if (target_is_remote ())
2192     {
2193       if (args == 0 || *args == 0)
2194         { /* XXX FIXME: what should default behavior be? */
2195           printf_filtered ("Usage: tfind range <startaddr>,<endaddr>\n");
2196           return;
2197         }
2198
2199       if (0 != (tmp = strchr (args, ',' )))
2200         {
2201           *tmp++ = '\0';        /* terminate start address */
2202           while (isspace (*tmp))
2203             tmp++;
2204           start = parse_and_eval_address (args);
2205           stop  = parse_and_eval_address (tmp);
2206         }
2207       else
2208         { /* no explicit end address? */
2209           start = parse_and_eval_address (args);
2210           stop  = start + 1; /* ??? */
2211         }
2212
2213       sprintf (target_buf, "QTFrame:range:%x:%x", start, stop);
2214       finish_tfind_command (target_buf, from_tty);
2215     }
2216   else
2217       error ("Trace can only be run on remote targets.");
2218 }
2219
2220 /* tfind outside command */
2221 static void
2222 trace_find_outside_command (args, from_tty)
2223      char *args;
2224      int from_tty;
2225 { /* STUB_COMM PART_IMPLEMENTED */
2226   CORE_ADDR start, stop;
2227   char *tmp;
2228
2229   if (target_is_remote ())
2230     {
2231       if (args == 0 || *args == 0)
2232         { /* XXX FIXME: what should default behavior be? */
2233           printf_filtered ("Usage: tfind outside <startaddr>,<endaddr>\n");
2234           return;
2235         }
2236
2237       if (0 != (tmp = strchr (args, ',' )))
2238         {
2239           *tmp++ = '\0';        /* terminate start address */
2240           while (isspace (*tmp))
2241             tmp++;
2242           start = parse_and_eval_address (args);
2243           stop  = parse_and_eval_address (tmp);
2244         }
2245       else
2246         { /* no explicit end address? */
2247           start = parse_and_eval_address (args);
2248           stop  = start + 1; /* ??? */
2249         }
2250
2251       sprintf (target_buf, "QTFrame:outside:%x:%x", start, stop);
2252       finish_tfind_command (target_buf, from_tty);
2253     }
2254   else
2255       error ("Trace can only be run on remote targets.");
2256 }
2257
2258 /* save-tracepoints command */
2259 static void
2260 tracepoint_save_command (args, from_tty)
2261      char *args;
2262      int from_tty;
2263 {
2264   struct tracepoint  *tp;
2265   struct action_line *line;
2266   FILE *fp;
2267   char *i1 = "    ", *i2 = "      ";
2268   char *indent, *actionline;
2269
2270   if (args == 0 || *args == 0)
2271     error ("Argument required (file name in which to save tracepoints");
2272
2273   if (tracepoint_chain == 0)
2274     {
2275       warning ("save-tracepoints: no tracepoints to save.\n");
2276       return;
2277     }
2278
2279   if (!(fp = fopen (args, "w")))
2280     error ("Unable to open file '%s' for saving tracepoints");
2281
2282   ALL_TRACEPOINTS (tp)
2283     {
2284       if (tp->addr_string)
2285         fprintf (fp, "trace %s\n", tp->addr_string);
2286       else
2287         fprintf (fp, "trace *0x%x\n", tp->address);
2288
2289       if (tp->pass_count)
2290         fprintf (fp, "  passcount %d\n", tp->pass_count);
2291
2292       if (tp->actions)
2293         {
2294           fprintf (fp, "  actions\n");
2295           indent = i1;
2296           for (line = tp->actions; line; line = line->next)
2297             {
2298               struct cmd_list_element *cmd;
2299
2300               QUIT;                     /* allow user to bail out with ^C */
2301               actionline = line->action;
2302               while (isspace(*actionline))
2303                 actionline++;
2304
2305               fprintf (fp, "%s%s\n", indent, actionline);
2306               if (*actionline != '#')   /* skip for comment lines */
2307                 {
2308                   cmd = lookup_cmd (&actionline, cmdlist, "", -1, 1);
2309                   if (cmd == 0)
2310                     error ("Bad action list item: %s", actionline);
2311                   if (cmd->function.cfunc == while_stepping_pseudocommand)
2312                     indent = i2;
2313                   else if (cmd->function.cfunc == end_actions_pseudocommand)
2314                     indent = i1;
2315                 }
2316             }
2317         }
2318     }
2319   fclose (fp);
2320   if (from_tty)
2321     printf_filtered ("Tracepoints saved to file '%s'.\n", args);
2322   return;
2323 }
2324
2325 /* info scope command: list the locals for a scope.  */
2326 static void
2327 scope_info (args, from_tty)
2328      char *args;
2329      int from_tty;
2330 {
2331   struct symtab_and_line sal;
2332   struct symtabs_and_lines sals;
2333   struct symbol *sym;
2334   struct minimal_symbol *msym;
2335   struct block *block;
2336   char **canonical, *symname, *save_args = args;
2337   int i, j, nsyms, count = 0;
2338
2339   if (args == 0 || *args == 0)
2340     error ("requires an argument (function, line or *addr) to define a scope");
2341
2342   sals = decode_line_1 (&args, 1, NULL, 0, &canonical);
2343   if (sals.nelts == 0)
2344     return;             /* presumably decode_line_1 has already warned */
2345
2346   /* Resolve line numbers to PC */
2347   resolve_sal_pc (&sals.sals[0]);
2348   block = block_for_pc (sals.sals[0].pc);
2349
2350   while (block != 0)
2351     {
2352       QUIT;                             /* allow user to bail out with ^C */
2353       nsyms = BLOCK_NSYMS (block);
2354       for (i = 0; i < nsyms; i++)
2355         {
2356           QUIT;                         /* allow user to bail out with ^C */
2357           if (count == 0)
2358             printf_filtered ("Scope for %s:\n", save_args);
2359           count++;
2360           sym = BLOCK_SYM (block, i);
2361           symname = SYMBOL_NAME (sym);
2362           if (symname == NULL || *symname == '\0')
2363             continue;   /* probably botched, certainly useless */
2364
2365           printf_filtered ("Symbol %s is ", symname);
2366           switch (SYMBOL_CLASS (sym)) {
2367           default:
2368           case LOC_UNDEF:               /* messed up symbol? */
2369             printf_filtered ("a bogus symbol, class %d.\n", 
2370                              SYMBOL_CLASS (sym));
2371             count--;                    /* don't count this one */
2372             continue;
2373           case LOC_CONST:
2374             printf_filtered ("a constant with value %d (0x%x)", 
2375                              SYMBOL_VALUE (sym), SYMBOL_VALUE (sym));
2376             break;
2377           case LOC_CONST_BYTES:
2378             printf_filtered ("constant bytes: ");
2379             if (SYMBOL_TYPE (sym))
2380               for (j = 0; j < TYPE_LENGTH (SYMBOL_TYPE (sym)); j++)
2381                 fprintf_filtered (gdb_stdout, " %02x",
2382                                   (unsigned) SYMBOL_VALUE_BYTES (sym) [j]);
2383             break;
2384           case LOC_STATIC:
2385             printf_filtered ("in static storage at address ");
2386             print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2387             break;
2388           case LOC_REGISTER:
2389             printf_filtered ("a local variable in register $%s",
2390                              REGISTER_NAME (SYMBOL_VALUE (sym)));
2391             break;
2392           case LOC_ARG:
2393           case LOC_LOCAL_ARG:
2394             printf_filtered ("an argument at stack/frame offset %ld",
2395                              SYMBOL_VALUE (sym));
2396             break;
2397           case LOC_LOCAL:
2398             printf_filtered ("a local variable at frame offset %ld",
2399                              SYMBOL_VALUE (sym));
2400             break;
2401           case LOC_REF_ARG:
2402             printf_filtered ("a reference argument at offset %ld",
2403                              SYMBOL_VALUE (sym));
2404             break;
2405           case LOC_REGPARM:
2406             printf_filtered ("an argument in register $%s",
2407                              REGISTER_NAME (SYMBOL_VALUE (sym)));
2408             break;
2409           case LOC_REGPARM_ADDR:
2410             printf_filtered ("the address of an argument, in register $%s",
2411                              REGISTER_NAME (SYMBOL_VALUE (sym)));
2412             break;
2413           case LOC_TYPEDEF:
2414             printf_filtered ("a typedef.\n");
2415             continue;
2416           case LOC_LABEL:
2417             printf_filtered ("a label at address ");
2418             print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
2419             break;
2420           case LOC_BLOCK:
2421             printf_filtered ("a function at address ");
2422             print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
2423                                    gdb_stdout);
2424             break;
2425           case LOC_BASEREG:
2426             printf_filtered ("a variable at offset %d from register $%s",
2427                              SYMBOL_VALUE (sym),
2428                              REGISTER_NAME  (SYMBOL_BASEREG (sym)));
2429             break;
2430           case LOC_BASEREG_ARG:
2431             printf_filtered ("an argument at offset %d from register $%s",
2432                              SYMBOL_VALUE (sym),
2433                              REGISTER_NAME  (SYMBOL_BASEREG (sym)));
2434             break;
2435           case LOC_UNRESOLVED:
2436             msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
2437             if (msym == NULL)
2438               printf_filtered ("Unresolved Static");
2439             else
2440               {
2441                 printf_filtered ("static storage at address ");
2442                 print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1, 
2443                                        gdb_stdout);
2444               }
2445             break;
2446           case LOC_OPTIMIZED_OUT:
2447             printf_filtered ("optimized out.\n");
2448             continue;
2449           }
2450           if (SYMBOL_TYPE (sym))
2451             printf_filtered (", length %d.\n", 
2452                              TYPE_LENGTH (check_typedef (SYMBOL_TYPE (sym))));
2453         }
2454       if (BLOCK_FUNCTION (block))
2455         break;
2456       else
2457         block = BLOCK_SUPERBLOCK (block);
2458     }
2459   if (count <= 0)
2460     printf_filtered ("Scope for %s contains no locals or arguments.\n",
2461                      save_args);
2462 }
2463
2464 /* worker function (cleanup) */
2465 static void
2466 replace_comma (comma)
2467      char *comma;
2468 {
2469   *comma = ',';
2470 }
2471
2472 /* tdump command */
2473 static void
2474 trace_dump_command (args, from_tty)
2475      char *args;
2476      int from_tty;
2477 {
2478   struct tracepoint  *t;
2479   struct action_line *action;
2480   char               *action_exp, *next_comma;
2481   struct cleanup     *old_cleanups;
2482   int                 stepping_actions = 0;
2483   int                 stepping_frame   = 0;
2484
2485   if (!target_is_remote ())
2486     {
2487       error ("Trace can only be run on remote targets.");
2488       return;
2489     }
2490
2491   if (tracepoint_number == -1)
2492     {
2493       warning ("No current trace frame.");
2494       return;
2495     }
2496
2497   ALL_TRACEPOINTS (t)
2498     if (t->number == tracepoint_number)
2499       break;
2500
2501   if (t == NULL)
2502     error ("No known tracepoint matches 'current' tracepoint #%d.", 
2503            tracepoint_number);
2504
2505   old_cleanups = make_cleanup (null_cleanup, NULL);
2506
2507   printf_filtered ("Data collected at tracepoint %d, trace frame %d:\n", 
2508                    tracepoint_number, traceframe_number);
2509
2510   /* The current frame is a trap frame if the frame PC is equal
2511      to the tracepoint PC.  If not, then the current frame was
2512      collected during single-stepping.  */
2513
2514   stepping_frame = (t->address != read_pc());
2515
2516   for (action = t->actions; action; action = action->next)
2517     {
2518       struct cmd_list_element *cmd;
2519
2520       QUIT;                             /* allow user to bail out with ^C */
2521       action_exp = action->action;
2522       while (isspace (*action_exp))
2523         action_exp++;
2524
2525       /* The collection actions to be done while stepping are
2526          bracketed by the commands "while-stepping" and "end".  */
2527
2528       if (*action_exp == '#')   /* comment line */
2529         continue;
2530
2531       cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
2532       if (cmd == 0)
2533         error ("Bad action list item: %s", action_exp);
2534
2535       if (cmd->function.cfunc == while_stepping_pseudocommand)
2536         stepping_actions = 1;
2537       else if (cmd->function.cfunc == end_actions_pseudocommand)
2538         stepping_actions = 0;
2539       else if (cmd->function.cfunc == collect_pseudocommand)
2540         {
2541           /* Display the collected data.
2542              For the trap frame, display only what was collected at the trap.
2543              Likewise for stepping frames, display only what was collected
2544              while stepping.  This means that the two boolean variables,
2545              STEPPING_FRAME and STEPPING_ACTIONS should be equal.  */
2546           if (stepping_frame == stepping_actions)
2547             {
2548               do { /* repeat over a comma-separated list */
2549                 QUIT;           /* allow user to bail out with ^C */
2550                 if (*action_exp == ',')
2551                   action_exp++;
2552                 while (isspace (*action_exp))
2553                   action_exp++;
2554
2555                 next_comma = strchr (action_exp, ',');
2556
2557                 if      (0 == strncasecmp (action_exp, "$reg", 4))
2558                   registers_info (NULL, from_tty);
2559                 else if (0 == strncasecmp (action_exp, "$loc", 4))
2560                   locals_info (NULL, from_tty);
2561                 else if (0 == strncasecmp (action_exp, "$arg", 4))
2562                   args_info (NULL, from_tty);
2563                 else
2564                   { /* variable */
2565                     if (next_comma)
2566                       {
2567                         make_cleanup (replace_comma, next_comma);
2568                         *next_comma = '\0';
2569                       }
2570                     printf_filtered ("%s = ", action_exp);
2571                     output_command (action_exp, from_tty);
2572                     printf_filtered ("\n");
2573                   }
2574                 if (next_comma)
2575                   *next_comma = ',';
2576                 action_exp = next_comma;
2577               } while (action_exp && *action_exp == ',');
2578             }
2579         }
2580     }
2581   discard_cleanups (old_cleanups);
2582 }
2583
2584 /* Convert the memory pointed to by mem into hex, placing result in buf.
2585  * Return a pointer to the last char put in buf (null)
2586  * "stolen" from sparc-stub.c
2587  */
2588
2589 static const char hexchars[]="0123456789abcdef";
2590
2591 static unsigned char *
2592 mem2hex(mem, buf, count)
2593      unsigned char *mem;
2594      unsigned char *buf;
2595      int count;
2596 {
2597   unsigned char ch;
2598
2599   while (count-- > 0)
2600     {
2601       ch = *mem++;
2602
2603       *buf++ = hexchars[ch >> 4];
2604       *buf++ = hexchars[ch & 0xf];
2605     }
2606
2607   *buf = 0;
2608
2609   return buf;
2610 }
2611
2612 int get_traceframe_number()
2613 {
2614  return traceframe_number;
2615 }
2616
2617
2618 /* module initialization */
2619 void
2620 _initialize_tracepoint ()
2621 {
2622   tracepoint_chain  = 0;
2623   tracepoint_count  = 0;
2624   traceframe_number = -1;
2625   tracepoint_number = -1;
2626
2627   set_internalvar (lookup_internalvar ("tpnum"), 
2628                    value_from_longest (builtin_type_int, (LONGEST) 0));
2629   set_internalvar (lookup_internalvar ("trace_frame"), 
2630                    value_from_longest (builtin_type_int, (LONGEST) -1));
2631
2632   if (tracepoint_list.list == NULL)
2633     {
2634       tracepoint_list.listsize = 128;
2635       tracepoint_list.list = xmalloc 
2636         (tracepoint_list.listsize * sizeof (struct memrange));
2637     }
2638   if (tracepoint_list.aexpr_list == NULL)
2639     {
2640       tracepoint_list.aexpr_listsize = 128;
2641       tracepoint_list.aexpr_list = xmalloc
2642         (tracepoint_list.aexpr_listsize * sizeof (struct agent_expr *));
2643     }
2644
2645   if (stepping_list.list == NULL)
2646     {
2647       stepping_list.listsize = 128;
2648       stepping_list.list = xmalloc 
2649         (stepping_list.listsize * sizeof (struct memrange));
2650     }
2651
2652   if (stepping_list.aexpr_list == NULL)
2653     {
2654       stepping_list.aexpr_listsize = 128;
2655       stepping_list.aexpr_list = xmalloc
2656         (stepping_list.aexpr_listsize * sizeof (struct agent_expr *));
2657     }
2658
2659   add_info ("scope", scope_info, 
2660             "List the variables local to a scope");
2661
2662   add_cmd ("tracepoints", class_trace, NO_FUNCTION, 
2663            "Tracing of program execution without stopping the program.", 
2664            &cmdlist);
2665
2666   add_info ("tracepoints", tracepoints_info,
2667             "Status of tracepoints, or tracepoint number NUMBER.\n\
2668 Convenience variable \"$tpnum\" contains the number of the\n\
2669 last tracepoint set.");
2670
2671   add_info_alias ("tp", "tracepoints", 1);
2672
2673   add_com ("save-tracepoints", class_trace, tracepoint_save_command, 
2674            "Save current tracepoint definitions as a script.\n\
2675 Use the 'source' command in another debug session to restore them.");
2676
2677   add_com ("tdump", class_trace, trace_dump_command, 
2678            "Print everything collected at the current tracepoint.");
2679
2680   add_prefix_cmd ("tfind",  class_trace, trace_find_command,
2681                   "Select a trace frame;\n\
2682 No argument means forward by one frame; '-' meand backward by one frame.",
2683                   &tfindlist, "tfind ", 1, &cmdlist);
2684
2685   add_cmd ("outside", class_trace, trace_find_outside_command,
2686            "Select a trace frame whose PC is outside the given \
2687 range.\nUsage: tfind outside addr1, addr2", 
2688            &tfindlist);
2689
2690   add_cmd ("range", class_trace, trace_find_range_command,
2691            "Select a trace frame whose PC is in the given range.\n\
2692 Usage: tfind range addr1,addr2", 
2693            &tfindlist);
2694
2695   add_cmd ("line", class_trace, trace_find_line_command,
2696            "Select a trace frame by source line.\n\
2697 Argument can be a line number (with optional source file), \n\
2698 a function name, or '*' followed by an address.\n\
2699 Default argument is 'the next source line that was traced'.",
2700            &tfindlist);
2701
2702   add_cmd ("tracepoint", class_trace, trace_find_tracepoint_command,
2703            "Select a trace frame by tracepoint number.\n\
2704 Default is the tracepoint for the current trace frame.",
2705            &tfindlist);
2706
2707   add_cmd ("pc", class_trace, trace_find_pc_command,
2708            "Select a trace frame by PC.\n\
2709 Default is the current PC, or the PC of the current trace frame.",
2710            &tfindlist);
2711
2712   add_cmd ("end", class_trace, trace_find_end_command,
2713            "Synonym for 'none'.\n\
2714 De-select any trace frame and resume 'live' debugging.",
2715            &tfindlist);
2716
2717   add_cmd ("none", class_trace, trace_find_none_command,
2718            "De-select any trace frame and resume 'live' debugging.",
2719            &tfindlist);
2720
2721   add_cmd ("start", class_trace, trace_find_start_command,
2722            "Select the first trace frame in the trace buffer.",
2723            &tfindlist);
2724
2725   add_com ("tstatus",  class_trace, trace_status_command,
2726            "Display the status of the current trace data collection.");
2727
2728   add_com ("tstop",  class_trace, trace_stop_command,
2729            "Stop trace data collection.");
2730
2731   add_com ("tstart", class_trace, trace_start_command,
2732            "Start trace data collection.");
2733
2734   add_com ("passcount", class_trace, trace_pass_command, 
2735            "Set the passcount for a tracepoint.\n\
2736 The trace will end when the tracepoint has been passed 'count' times.\n\
2737 Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
2738 if TPNUM is omitted, passcount refers to the last tracepoint defined.");
2739
2740   add_com ("end", class_trace, end_actions_pseudocommand,
2741            "Ends a list of commands or actions.\n\
2742 Several GDB commands allow you to enter a list of commands or actions.\n\
2743 Entering \"end\" on a line by itself is the normal way to terminate\n\
2744 such a list.\n\n\
2745 Note: the \"end\" command cannot be used at the gdb prompt.");
2746
2747   add_com ("while-stepping", class_trace, while_stepping_pseudocommand,
2748            "Specify single-stepping behavior at a tracepoint.\n\
2749 Argument is number of instructions to trace in single-step mode\n\
2750 following the tracepoint.  This command is normally followed by\n\
2751 one or more \"collect\" commands, to specify what to collect\n\
2752 while single-stepping.\n\n\
2753 Note: this command can only be used in a tracepoint \"actions\" list.");
2754
2755   add_com_alias ("ws",         "while-stepping", class_alias, 0);
2756   add_com_alias ("stepping",   "while-stepping", class_alias, 0);
2757
2758   add_com ("collect", class_trace, collect_pseudocommand, 
2759            "Specify one or more data items to be collected at a tracepoint.\n\
2760 Accepts a comma-separated list of (one or more) expressions.  GDB will\n\
2761 collect all data (variables, registers) referenced by that expression.\n\
2762 Also accepts the following special arguments:\n\
2763     $regs   -- all registers.\n\
2764     $args   -- all function arguments.\n\
2765     $locals -- all variables local to the block/function scope.\n\
2766 Note: this command can only be used in a tracepoint \"actions\" list.");
2767
2768   add_com ("actions", class_trace, trace_actions_command,
2769            "Specify the actions to be taken at a tracepoint.\n\
2770 Tracepoint actions may include collecting of specified data, \n\
2771 single-stepping, or enabling/disabling other tracepoints, \n\
2772 depending on target's capabilities.");
2773
2774   add_cmd ("tracepoints", class_trace, delete_trace_command, 
2775            "Delete specified tracepoints.\n\
2776 Arguments are tracepoint numbers, separated by spaces.\n\
2777 No argument means delete all tracepoints.",
2778            &deletelist);
2779
2780   add_cmd ("tracepoints", class_trace, disable_trace_command, 
2781            "Disable specified tracepoints.\n\
2782 Arguments are tracepoint numbers, separated by spaces.\n\
2783 No argument means disable all tracepoints.",
2784            &disablelist);
2785
2786   add_cmd ("tracepoints", class_trace, enable_trace_command, 
2787            "Enable specified tracepoints.\n\
2788 Arguments are tracepoint numbers, separated by spaces.\n\
2789 No argument means enable all tracepoints.",
2790            &enablelist);
2791
2792   add_com ("trace", class_trace, trace_command,
2793            "Set a tracepoint at a specified line or function or address.\n\
2794 Argument may be a line number, function name, or '*' plus an address.\n\
2795 For a line number or function, trace at the start of its code.\n\
2796 If an address is specified, trace at that exact address.\n\n\
2797 Do \"help tracepoints\" for info on other tracepoint commands.");
2798
2799   add_com_alias ("tp",   "trace", class_alias, 0);
2800   add_com_alias ("tr",   "trace", class_alias, 1);
2801   add_com_alias ("tra",  "trace", class_alias, 1);
2802   add_com_alias ("trac", "trace", class_alias, 1);
2803 }
2804