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