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